传送门:http://begin.lydsy.com/JudgeOnline/problem.php?id=2797
题目大意:给你几个串求出几个串中的最长公共子串。
题解:先看n最大才5,所以很容易想到暴力写法,因为最近在学后缀自动机就写写后缀自动机吧。
我们将第一个串作为母串,然后在用其他的串与它进行匹配,并且记录下其匹配中每个状态的最大匹配数,答案则为每个状态的最大匹配的最小值中的最大值。。(绕晕了)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define N 4005 7 using namespace std; 8 int last,root,tot; 9 char s[N]; 10 int n,m,ans; 11 struct data{ 12 int son[N][26],fa[N],val[N],ans[N],sum[N],tmp[N],smin[N]; 13 void prepare(){root=last=tot=1;} 14 int newnode(int x){val[++tot]=x; return tot;} 15 void extend(int x) 16 { 17 int p=last,np=newnode(val[p]+1); 18 for (; p && !son[p][x]; p=fa[p]) son[p][x]=np; 19 if (!p) fa[np]=root; 20 else 21 { 22 int q=son[p][x]; 23 if (val[p]+1==val[q]) fa[np]=q; 24 else 25 { 26 int nq=newnode(val[p]+1); 27 memcpy(son[nq],son[q],sizeof(son[q])); 28 fa[nq]=fa[q]; fa[q]=fa[np]=nq; 29 for (; p&& son[p][x]==q; p=fa[p]) son[p][x]=nq; 30 } 31 } 32 last=np; 33 } 34 void sort() 35 { 36 memset(sum,0,sizeof(sum)); 37 for (int i=1; i<=tot; i++) ans[i]=val[i]; 38 for (int i=1; i<=tot; i++) sum[val[i]]++; 39 for (int i=1; i<=tot; i++) sum[i]+=sum[i-1]; 40 for (int i=1; i<=tot; i++) tmp[sum[val[i]]--]=i; 41 } 42 void work() 43 { 44 scanf("%s",s+1); m=strlen(s+1); 45 memset(smin,0,sizeof(smin));int len=0;last=root; 46 for (int i=1; i<=m; i++) 47 { 48 int x=s[i]-‘a‘; 49 if (son[last][x]) last=son[last][x],len++; 50 else 51 { 52 for (; last&&!son[last][x];)last=fa[last]; 53 if (!last) len=0,last=root; 54 else 55 { 56 len=val[last]+1; last=son[last][x]; 57 } 58 } 59 smin[last]=max(smin[last],len); 60 } 61 for (int i=tot; i>=1; i--) 62 { 63 int x=tmp[i]; 64 ans[x]=min(ans[x],smin[x]); 65 if (fa[x] && smin[x]) smin[fa[x]]=val[fa[x]]; 66 } 67 } 68 }SAM; 69 int main() 70 { 71 scanf("%d\n",&n); n--; 72 SAM.prepare(); 73 scanf("%s",s+1); int len=strlen(s+1); 74 for (int i=1; i<=len; i++) SAM.extend(s[i]-‘a‘); 75 SAM.sort(); 76 for (int i=1; i<=n; i++) SAM.work(); 77 for (int i=1; i<=tot; i++) ans=max(ans,SAM.ans[i]);//,cout<<i<<" "<<SAM.ans[i]<<endl; 78 printf("%d\n",ans); 79 }
注意:我们在写的过程中,每到一个状态我们要不断跟新之前的状态答案,我们可以用dfs或者利用right数组的特性来更新,具体细节看看代码。
时间: 2024-11-08 20:20:05