当先锋百科网

首页 1 2 3 4 5 6 7

参考资料
KMP算法易懂版
从头到尾彻底理解KMP
KMP算法之求next数组代码讲解
我觉得最主要是理解这个图,理解为什么要递归next[k]
在这里插入图片描述
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
在这里插入图片描述

解法一 枚举

遍历所有可能的情况,算法超时

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int len = s.length();
        if(len < 2) return false;
        for(int i = 1; i <= len/2;i++){
            if(len % i != 0) continue;
            string ans = "";
            string tmp = s.substr(0,i);
            for(int j = 1;j <= len/i;j++){
                ans = ans + tmp;
            }
            if(ans.compare(s)==0) return true;             
          
            
        }
        return false;
    }
};

解法二

参考官方题解

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        return (s + s).find(s, 1) != s.size();
    }
};

解法三 KMP

数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int k = -1,p = 0;
        int n = s.length();
        vector<int> next(n + 1);
        next[0] = -1;
        while(p < n){
            if(k == -1 || s[p] == s[k]){
                p++;k++;
                next[p] = k;
            }
            else
                k = next[k];
        }
        int m = n - next[n];
        if(next[n] != 0 && n % m == 0) return true;
        else return false;
    }
};

算next数组的时候,p是要求的字符串第p个位置的next[p],k是要比较的字符串索引,这种方式求的next数组第一位是-1,与最长前缀后缀恰好错开一位,所以让next数组大小为n+1,最后一位n+1存储的其实是第n位求的next。
防止自己忘记,记录一下。

leetcode28 正规的求kmp代码

class Solution {
public:
    int strStr(string haystack, string needle) {
    if(needle.length() == 0) return 0;       
        vector<int> next(needle.length());
        next[0] = -1;
        int p = 0,k = -1;
        while(p < needle.length() - 1){
            if(k == -1 || needle[p] == needle[k]){
                p++;k++; 
                next[p] = k;                       
            }
            else k = next[k];
        }
        int i = 0,j = 0;
        int x = haystack.length();
        int y = needle.length();
        while(i <x && j < y){
            
            if(j == -1 || haystack[i] == needle[j]){
                i++;j++;
            }
            else {
                j = next[j];
            }
        }
        if(j == needle.length()) return i - j;
        else return -1;
    }
};