代码随想录 第九天 | 烤馍片(kmp)算法 ●28. 实现 strStr() ●459.重复的子字符串

烤馍片算法(kmp):为了不让遍历的指针回退,每次不相等的时候找不相等之前的字符串的最长相等前后缀。i表示目标字符串,j表示需要在目标找到的字符串的指针。最长相等前后缀的长度就是之前有多少个与needle字符串相同,直接将j跳到上一元素位置记录的最长相等前后缀长度(next数组),这样i就可以一直++,当j==needle的长度时,证明找到完整needle字符串。

 

leetcode:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

class Solution {
    public void getNext(String haystack,int[] next){

        next[0] = 0;
        for(int i = 0,j = 0; i < haystack.length();i++){
            //不相等下标就找hastack上一个。
            while(j > 0 &&haystack.charAt(i) != haystack.charAt(j)){
                j = next[j - 1];
            }
            //相等++
            if(haystack.charAt(i) == haystack.charAt(j) ){
                j++;
            }
            //j的值就是最长相等后缀的长度
            next[i] = j;
        }
    }
    public int strStr(String haystack, String needle) {
        if(needle.length() == 0){
            return 0;
        }
        int [] next = new int[needle.length()];
        getNext(needle,next);
            int j = 0;
            for(int i = 0;i < haystack.length();i++){
                //判断字符串相等
                //不相等就退needle字符串上一位置,这个位置具体的数据需要next数组
                while (j > 0 && haystack.charAt(i) != needle.charAt(j)){
                    j = next[j-1];
                }
                if(haystack.charAt(i) == needle.charAt(j)){
                    j++;
                }
                if( j == needle.length()){
                    //加一是因为数组起始为0
                    return (i - needle.length() + 1);
                }
            }
            return -1;

    }


}

 LeetCode:459. 重复的子字符串 - 力扣(LeetCode)(跳)

思路:最长相等前后缀不包含的子串就是最小重复子串,总长度-最长前后缀长度,剩下的只要能被总长度整除就说明是重复字符串

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        if (s.equals("")) return false;

        int len = s.length();
        // 原串加个空格(哨兵),使下标从1开始,这样j从0开始,也不用初始化了
        s = " " + s;
        char[] chars = s.toCharArray();
        int[] next = new int[len + 1];
这里还是看上题的next吧
        // 构造 next 数组过程,j从0开始(空格),i从2开始
        for (int i = 2, j = 0; i <= len; i++) {
            // 匹配不成功,j回到前一位置 next 数组所对应的值
            while (j > 0 && chars[i] != chars[j + 1]) j = next[j];
            // 匹配成功,j往后移
            if (chars[i] == chars[j + 1]) j++;
            // 更新 next 数组的值
            next[i] = j;
        }

        // 最后判断是否是重复的子字符串,这里 next[len] 即代表next数组末尾的值
        if (next[len] > 0 && len % (len - next[len]) == 0) {
            return true;
        }
        return false;
    }
}

 

posted @ 2024-03-01 22:09  22软工冷薄  阅读(4)  评论(0编辑  收藏  举报