还是直接上转移方程:
动规只能解决O(n^2)的最长公共子串问题
使用后缀数组或者SAM可以高效地解决这个问题
所以,对于这个问题,动规的代码就不给出了
直接给出SAM的实现,也为以后学习SAM打下一个基础
具体做法是,对一个串建后缀自动机,把另一个串在自动机上跑,维护一下最大的匹配的长度就好了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int n,ans; 6 char s[1000005]; 7 struct Node 8 { 9 int siz,rt,last; 10 int fa[1500005],maxl[1500005]; 11 int ch[1500005][30]; 12 Node(){siz=rt=last=1;} 13 int newnode(int x) 14 { 15 maxl[++siz]=x; 16 return siz; 17 } 18 void add(int x,int i) 19 { 20 int p=last,np=newnode(maxl[p]+1); 21 while(p&&ch[p][i]==0) ch[p][i]=np,p=fa[p]; 22 if(p==0) fa[np]=rt; 23 else 24 { 25 int q=ch[p][i]; 26 if(maxl[q]==maxl[p]+1) fa[np]=q; 27 else 28 { 29 int r=newnode(maxl[p]+1); 30 memcpy(ch[r],ch[q],sizeof(ch[r])); 31 fa[r]=fa[q]; 32 fa[q]=fa[np]=r; 33 while(p&&ch[p][i]==q) 34 ch[p][i]=r,p=fa[p]; 35 } 36 } 37 last=np; 38 } 39 void solve() 40 { 41 int p=rt,len=0; 42 for(int i=1;i<=n;i++) 43 { 44 while(p&&ch[p][s[i]-'a']==0) 45 p=fa[p],len=maxl[p]; 46 if(p==0) p=rt,len=0; 47 else p=ch[p][s[i]-'a'],len++; 48 ans=max(ans,len); 49 } 50 } 51 }sam; 52 int main() 53 { 54 scanf("%s",s+1); 55 n=strlen(s+1); 56 for(int i=1;i<=n;i++) sam.add(i,s[i]-'a'); 57 scanf("%s",s+1); 58 n=strlen(s+1); 59 sam.solve(); 60 printf("%d",ans); 61 return 0; 62 }
我在敲的时候有一种不舒适的感觉,可能是SAM太强大了,日后赶紧学习一波