这是一个很好的算法思想 需要数形结合不然难理解欸
首先看next数组这是对模板串的一个操作
例如 abababab
不论哪一个模板串 next[1]一定为0
其次看
next[2]=0 解释只看前两个字符 ab 那么它的前缀为 a 后缀为 b显然没有相等的
next[3]=1 解释只看前三个字符 aba 那么它的前缀为 a,ab 后缀为 a,ba显然只有字符长度为1的时候相等
next[4]=2 解释只看前四个字符 abab 那么它的前缀为 a,ab,aba 后缀为 a,ab,bab显然有字符长度为1,2的时候相等(取最大)
next[5] ...
next[6] ...
next[7] ...
next[8] ...
这样我们next数组就完成了
之后就是比较操作了
假设碰巧在圆圈处不相等 即s[i]!=p[j+1]前面的都相等 那么
可以看到我们已知蓝色两个区域相等右边蓝色又和左边蓝色相等那么粉色就和左边蓝色相等那么就可以让j移动到ne[j]
向上图这样从ne[j]+1开始比直到j=n 就说明存在与模板串相等的子串
code:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,M=1000010;
char p[N],s[M];//p为模板串 s为要查询的串
int n,m,ne[N];
int main(){
cin>>n>>p+1>>m>>s+1;
for(int i=2,j=0;i<=n;i++){
while(j&&p[i]!=p[j+1])j=ne[j];
if(p[i]==p[j+1])j++;
ne[i]=j;
}//完成next数组
for(int i=1,j=0;i<=m;i++){
while(j&&s[i]!=p[j+1])j=ne[j];
if(s[i]==p[j+1])j++;
if(j==n){
cout<<i-n<<" ";
j=ne[j];//因为存在可能不止一个所以退回去重新找
}
}
}