260724strC CF1721E KMP自动机学习笔记
KMP 自动机模板题。前置知识:KMP。
如果每次暴力 KMP 求解,时间复杂度
首先可以发现,
观察我们从
那么我们有转移:
那么对于当前指针
时间复杂度为
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+1e5+2;
int nxt[N];
int tr[N][30];
//tr[i][j] 表示 不停沿着 nxt[] 往上跳,使得 s_{k+1}=j 的 k
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
string s;cin>>s;int n=s.size();s=" "+s;
for(int i=1,j=0; i<=n; ){
if(!j || s[i]==s[j]) nxt[++i]=++j;
else j=nxt[j];
}
for(int i=1; i<=n; i++) nxt[i]=nxt[i+1]-1;
for(int i=0; i<n; i++){
for(int c=0; c<26; c++) tr[i][c]=tr[nxt[i]][c];
tr[i][s[i+1]-'a']=i;
}
int q;cin>>q;
while(q--){
string t;cin>>t;int m=t.size();s+=t;
for(int i=n+1,j=nxt[n]; i<=n+m; i++){
j=tr[j][s[i]-'a']+1; // s_j=s_i / tr_{...}=0
if(s[i]!=s[j]) j=0; // 特判!
nxt[i]=j;cout<<j<<" ";
for(int c=0; c<26; c++) tr[i-1][c]=tr[nxt[i-1]][c];
tr[i-1][s[i]-'a']=i-1;
}
for(int i=n+1; i<=n+m; i++) s.pop_back();
cout<<"\n";
}
return 0;
}