• 1397. 找到所有好字符串 KMP+数位dp


    1397. 找到所有好字符串

    给你两个长度为 n 的字符串 s1 和 s2 ,以及一个字符串 evil 。请你返回 好字符串 的数目。

    好字符串 的定义为:它的长度为 n ,字典序大于等于 s1 ,字典序小于等于 s2 ,且不包含 evil 为子字符串。

    由于答案可能很大,请你返回答案对 10^9 + 7 取余的结果。

    示例 1:

    输入:n = 2, s1 = "aa", s2 = "da", evil = "b"
    输出:51 
    解释:总共有 25 个以 'a' 开头的好字符串:"aa","ac","ad",...,"az"。还有 25 个以 'c' 开头的好字符串:"ca","cc","cd",...,"cz"。最后,还有一个以 'd' 开头的好字符串:"da"。
    

    示例 2:

    输入:n = 8, s1 = "leetcode", s2 = "leetgoes", evil = "leet"
    输出:0 
    解释:所有字典序大于等于 s1 且小于等于 s2 的字符串都以 evil 字符串 "leet" 开头。所以没有好字符串。
    

    示例 3:

    输入:n = 2, s1 = "gx", s2 = "gz", evil = "x"
    输出:2
    

    提示:

    • s1.length == n
    • s2.length == n
    • s1 <= s2
    • 1 <= n <= 500
    • 1 <= evil.length <= 50
    • 所有字符串都只包含小写英文字母。

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/find-all-good-strings
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    做题结果

    成功,就是花了好几个小时,开始没想到KMP,后面想到了但是不知道怎么写,现找板子贴的

     方法:KMP+数位dp

    1. 由于涉及字符串匹配,所以需要用到KMP,就是ABCABD,这种字符串,如果给定 ABCABC,最后一个C要配到 ABC 的位置

    2. 数位 dp 和前面几天写的类似,都是上限,下限,这部分不再细讲

    2. 特色部分:匹配长度全的情况不能记录,因为题目要求不能全匹配;dp二维条件为匹配长度,即为到达某个位置 i 时,在匹配长度为 j 的情况下,后续能找到多少好字符串

    1. class Solution {
    2. long[][] dp;
    3. char[] down;
    4. char[] up;
    5. int n;
    6. char[] devil;
    7. int[] next;
    8. long MOD = (long) (1e9+7);
    9. public int findGoodStrings(int n, String s1, String s2, String evil) {
    10. this.n = n;
    11. down = s1.toCharArray();
    12. up = s2.toCharArray();
    13. devil = evil.toCharArray();
    14. next = getNext(evil);
    15. dp = new long[n][devil.length];
    16. for(int i = 0; i< n; i++) Arrays.fill(dp[i],-1);
    17. int ans = (int) dfs(true,true,0,0);
    18. return ans;
    19. }
    20. public int[] getNext(String ps) {
    21. char[] p = ps.toCharArray();
    22. int n = p.length;
    23. int[] next = new int[n];
    24. int i = 0;
    25. int j = -1;
    26. next[0] = -1;
    27. while(i1){
    28. if(j==-1 || p[i]==p[j]){
    29. next[++i]=++j;
    30. }else{
    31. j = next[j];
    32. }
    33. }
    34. next[0]=0;
    35. return next;
    36. }
    37. private long dfs(boolean limitUp, boolean limitDown, int index, int matchDevil){
    38. if(index==n) return 1;
    39. if(!limitUp && !limitDown && dp[index][matchDevil]!=-1) return dp[index][matchDevil];
    40. long ans = 0;
    41. char min = limitDown?down[index]:'a';
    42. char max = limitUp?up[index]:'z';
    43. for(char i = min; i <= max; i++){
    44. int matchEvilLen = matchDevil;
    45. if(i==devil[matchDevil]){
    46. matchEvilLen = matchDevil+1;
    47. }else {
    48. //关键:KMP不匹配的情况,需要一直往前搜索,而不能找不到直接结束
    49. while (next[matchEvilLen] > 0 && devil[next[matchEvilLen]] != i) {
    50. matchEvilLen = next[matchEvilLen];
    51. }
    52. if (devil[next[matchEvilLen]] == i) {
    53. matchEvilLen = next[matchEvilLen] + 1;
    54. } else {
    55. matchEvilLen = 0;
    56. }
    57. }
    58. if(matchEvilLen==devil.length)
    59. continue;
    60. ans = (ans + dfs(limitUp&&i==max,limitDown&&i==min,index+1,matchEvilLen)%MOD)%MOD;
    61. }
    62. if(!limitUp && !limitDown) dp[index][matchDevil] = ans;
    63. return ans;
    64. }
    65. }

  • 相关阅读:
    在C++中怎么把std::string类型的数字转成int类型的数字
    vue的模板编译原理
    mac安装 scala 详细教程(包含在 idea 上使用,以及scala插件安装)
    云耀服务器L实例部署Nextcloud企业云盘系统|华为云云耀云服务器L实例评测使用体验
    免root修改手机imei的技术原理是什么?如何实现的?hook吗
    mysql-5:多表关系
    DEJA_VU3D - Cesium功能集 之 088-军事标绘系列十七:防御阵型
    构建用户身份基础设施,推动新能源汽车高质量发展
    已经有 MESI 协议,为什么还需要 volatile 关键字?
    Git安装、原理、常用命令、版本控制、如何上传普通文件到仓库以及如何修改IDEA中Terminal为git窗口
  • 原文地址:https://blog.csdn.net/yu_duan_hun/article/details/126442239