KMPnext数组自看
next[i]表示去掉第i且i之后的元素,自已的前缀和后缀最大匹配长度
例
字符串 a b a b a b z a b a b a b a
next -1 0 0 1 2 3 4 0 1 2 3 4 5 6 0
前缀和后缀是啥意思呢
例
abababz 前缀有 a ab aba abab ababa ababab 不算最后一个
后缀有 z bz abz babz ababz bababz 不算第一个
void getNext()
{
int j, k;
j = 0; k = -1; next[0] = -1;
while(j < tlen)
if(k == -1 || T[j] == T[k])
next[++j] = ++k;
else
k = next[k];
}
根据代码一个个匹配就好了
关键在于next的回溯 为什么要这样回溯
目的就是要找次大匹配长度,然后继续比较
那为什么next[k]就是次大匹配长度呢?
设想
0 1 2 3 4 5 6 7
next[7] = 5
也就是
0 1 2 3 4
2 3 4 5 6
匹配
那么
0 1 2
2 3 4
匹配
所以
next[5] = 3
也就是要证明次大长度为3
反证一下就好了
bin神kmp模板
/* pku3461(Oulipo), hdu1711(Number Sequence) 这个模板 字符串是从0开始的 Next数组是从1开始的 */ #include <iostream> #include <cstring> using namespace std; const int N = 1000002; int next[N]; char S[N], T[N]; int slen, tlen; void getNext() { int j, k; j = 0; k = -1; next[0] = -1; while(j < tlen) if(k == -1 || T[j] == T[k]) next[++j] = ++k; else k = next[k]; } /* 返回模式串T在主串S中首次出现的位置 返回的位置是从0开始的。 */ int KMP_Index() { int i = 0, j = 0; getNext(); while(i < slen && j < tlen) { if(j == -1 || S[i] == T[j]) { i++; j++; } else j = next[j]; } if(j == tlen) return i - tlen; else return -1; } /* 返回模式串在主串S中出现的次数 */ int KMP_Count() { int ans = 0; int i, j = 0; if(slen == 1 && tlen == 1) { if(S[0] == T[0]) return 1; else return 0; } getNext(); for(i = 0; i < slen; i++) { while(j > 0 && S[i] != T[j]) j = next[j]; if(S[i] == T[j]) j++; if(j == tlen) { ans++; j = next[j]; } } return ans; } int main() { int TT; int i, cc; cin>>TT; while(TT--) { cin>>S>>T; slen = strlen(S); tlen = strlen(T); cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()<<endl; cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl; } return 0; } /* test case aaaaaa a abcd d aabaa b */
题目练习:
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号