KMP算法例题
链接:https://codeforces.com/contest/1200/problem/E
题意:依次合并两个单词,每次合并将删去最长相同前后缀,输出结果。
思路:用kmp跑出每个需要被连接的单词的next数组,与之前的单词进行匹配,跑出最长前后缀的长度并更新结果。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10; 4 int kmp[maxn]; 5 char ans[maxn]; 6 char b[maxn]; 7 int main() 8 { 9 int T; 10 scanf("%d",&T); 11 T--; 12 scanf("%s",ans+1); 13 int anslen=strlen(ans+1); 14 while(T--){ 15 scanf("%s",b+1); 16 int len=strlen(b+1); 17 kmp[0]=kmp[1]=0; 18 int j=0; 19 for(int i=2;i<=len;i++){ 20 while(j&&b[i]!=b[j+1]) 21 j=kmp[j]; 22 if(b[j+1]==b[i])j++; 23 kmp[i]=j; 24 } 25 j=0; 26 for(int i=max(1,anslen-len+1);i<=anslen;i++){ 27 while(j>0&&b[j+1]!=ans[i]) 28 j=kmp[j]; 29 if(b[j+1]==ans[i]) 30 j++; 31 } 32 int t=anslen; 33 for(int i=j+1;i<=len;i++){ 34 ans[++t]=b[i]; 35 } 36 anslen=t; 37 } 38 for(int i=1;i<=anslen;i++) 39 printf("%c",ans[i]); 40 printf("\n"); 41 }
第二套代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10; 4 int net[maxn]; 5 int main() 6 { 7 ios::sync_with_stdio(0); 8 cin.tie(0); 9 string ans; 10 int n,ans_sz; 11 cin>>n>>ans; 12 for(int i=1;i<n;i++){ 13 string tmp; cin>>tmp; 14 int sz=tmp.size(); 15 int p=0; net[0]=net[1]=0; 16 for(int i=2;i<=sz;i++){ 17 while(p&&tmp[i-1]!=tmp[p]) p=net[p]; 18 if(tmp[i-1]==tmp[p]) p++; 19 net[i]=p; 20 } 21 p=0; //最长相同前后缀长度 22 ans_sz=ans.size(); 23 for(int i=max(1,ans_sz-sz+1);i<=ans_sz;i++){ 24 while(p&&ans[i-1]!=tmp[p]) p=net[p]; 25 if(ans[i-1]==tmp[p]) p++; 26 } 27 for(int i=p;i<sz;i++) ans+=tmp[i]; 28 } 29 cout<<ans<<endl; 30 return 0; 31 }