[leetcode]Repeated Substring Pattern顺带复习KMP

来源:互联网 发布:计算微积分的软件 编辑:程序博客网 时间:2024/06/07 20:15

虽然是easy题型,但是想要高效的实现,还是得用KMP的思想啊。。

PS:一遇到next数组就歇菜。。原因是对next数组含义理解不透彻。。不能再这样下去了。。

  • next[i]=j;表示到i前面字符串与原始字符匹配的子串长度。因此,next[n+1]数组需要开n+1大小
bool repeatedSubstringPattern(string s) {    int i = 1;    int j = 0;    int n = s.size();    vector<int> next(n + 1, 0);    while (i < n) {        if (s[i] == s[j]) next[++i] = ++j;        else {            if (j == 0) ++i;            else j = next[j]; //eg:abacabad           }    }    return next[n] && (next[n] % (n - next[n])) == 0;}

原串:abacabad
模式: abacabad

此时next数组

a b a c a b a d + 0 0 0 1 0 1 2 3 0

i = 7 , j = 3是 str[i]=’d’ str[j]=’c’发生了失配,此时需要往回看,看看j之前的(有共同前缀aba的)前缀串中有没有可匹配的模式,于是j=dp[3]=1,str[i]=’d’ str[j]=’b’仍然失配,继续往回看j=0,str[i]=’d’,str[0]=’a’还是失配,那就没办法了。。。

KMP算法

#include <iostream>#include <vector>using namespace std;vector<int> calNext(string str){    int i = 1, j = 0, n = str.size();    vector<int> dp(n + 1, 0);    dp[0] = -1;    while (i < n)    {        if (str[i] == str[j]) dp[++i] = ++j;        else {            if (j == 0) ++i;            else j = dp[j];        }    }    for(int i = 0; i <= n; ++i)    {        cout << dp[i] << " ";    }    cout << endl;    return dp;}// 输出匹配首坐标int kmpSearch(string s, string p) {    vector<int> next = calNext(p);    int slen = s.size();    int plen = p.size();    int i = 0;    int j = 0;    while(i < slen && j < plen) {        if (j == -1 || s[i] == p[j]) { // j == -1从头开始匹配。。。            ++i;            ++j;        } else {            j = next[j];        }    }    if (j == plen) {        return i - j;    } else {        return -1;    }}void test2() {    string s = "abacababc";    string p = "abab";    cout << kmpSearch(s, p) << endl;}int main(){    test2();    return 0;}
原创粉丝点击