AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010,M = 1000010;
int n,m;
char p[N],s[M];
int ne[N];
int main()
{
cin>>n>>p+1>>m>>s+1;
for(int i=2,j=0;i<=n;i++)
{
while(j&&p[j+1]!=p[i])j=ne[j];
if(p[j+1]==p[i])j++;
ne[i]=j;
}
for(int i=1,j=0;i<=m;i++)
{
while(j&&s[i]!=p[j+1])j=ne[j];
if(p[j+1]==s[i])j++;
if(j==n)
{
cout<<i-n<<" ";
j=ne[j];
}
}
return 0;
}
相关解释:
这里在进行匹配的时候,j表示的含义是对于每个i而言已经匹配了j个字符,然后这里判断j+1和i是是不是匹配的,如果不匹配j=ne[j],这里的ne[i]表示的是p[i]包含i前面最大的前后缀的长度,所以就可以直接移动了。注意这里匹配完成的话,在下一次匹配的时候,j=ne[j],然后再继续进行匹配。
求ne数组的话,如果不好理解,就可以先写KMP匹配过程,然后再写next数组构造过程,就相当于把s写成p,然后在更新每个ne[i]的值。刚开始的话,ne[1]=0,因为只有一个字符的话,最大的前后缀长度为0,因为不可以超过i本身,否则移动跟没移动一样。