KMP算法
模板 ```cpp #include<bits/stdc++.h> using namespace std; const int N=100010; char q[N],a[N]; int ne[N]; int main() { int n,m; cin>>n>>q+1>>m>>a+1; for(int i=2,j=0;i<=n;i++) { while(j&&q[i]!=q[j+1]) j=ne[j]; if(q[i]==q[j+1]) j++; ne[i]=j; } for(int i=1,j=0;i<=m;i++) { while(j&&a[i]!=q[j+1]) j=ne[j]; if(a[i]==q[j+1]) j++; if(j==n) { cout<<i-n<<" "; j=ne[j]; } } } ```
解决什么样的问题:
字符串匹配。给你两个字符串,寻找其中一个字符串是否包含另一个字符串,如果包含,返回包含的起始位置。
如下面两个字符串:
char *str = "bacbababadababacambabacaddababacasdsd";
char *ptr = "ababaca";
str有两处包含ptr
分别在str的下标10,26处包含ptr。
next数组:
考察 “ababaca”
这里我们要计算一个长度为m的转移函数next。
next数组的含义就是一个固定字符串的最长前缀和最长后缀相同的长度。
比如:abcjkdabc,那么这个数组的最长前缀和最长后缀相同必然是abc。
cbcbc,最长前缀和最长后缀相同是cbc。
abcbc,最长前缀和最长后缀相同是不存在的。
**注意最长前缀:是说以第一个字符开始,但是不包含最后一个字符。
比如aaaa相同的最长前缀和最长后缀是aaa。**
对于目标字符串ptr,ababaca,长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是
a,ab,aba,abab,ababa,ababac,ababaca的相同的最长前缀和最长后缀的长度。
由于a,ab,aba,abab,ababa,ababac,ababaca的相同的最长前缀和最长后缀是“”,“”,“a”,“ab”,“aba”,“”,“a”,所以next数组的值是[-1,-1,0,1,2,-1,0],这里-1表示不存在,0表示存在长度为1,2表示存在长度为3。这是为了和代码相对应。

如何预处理next数组:(借了acwing 上四谷夕雨的图 )

此时我们就可以求出长度为i的子串中与最长前缀相等的最长后缀!
for(int i = 2, j = 0; i <= m; i++) { while(j && p[i] != p[j+1]) j = next[j]; if(p[i] == p[j+1]) j++; next[i] = j; }

浙公网安备 33010602011771号