序列型动态规划之最长公共子串

还是直接上转移方程:

动规只能解决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太强大了,日后赶紧学习一波

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9473264.html