题链:
http://www.spoj.com/problems/LCS2/
题解:
后缀自动机。
对第一个串建立后缀自动机,
然后把后面的每个串分别与该串的自动机去匹配,求出相应的数组val*[s]:
表示第*个串与第一个串的自动机的状态s的最大匹配长度,
(求法就是两个串用后缀自动机求LCS这一过程):
对于当前已经匹配的子串T,长度为now,此刻在状态s,现在要匹配第i个字符x,
若trans(s,x)!=0,则s=trans(s,x),now++,i++,并更新val*[s]=max(val*[s],now);
否则,s=parent[s],直到trans(s,x)!=0或者s=0。
由于我们在每一步更新s时,没有更新到其祖先,所以最后再桶排之后去依次更新父亲。
而最后的状态s和每个串的最大匹配长度就是min(min(val*[s]),maxs[s](这个是状态s所允许的最大长度));
代码:
#include<bits/stdc++.h> #define MAXN 100005 #define INF 0x3f3f3f3f using namespace std; struct SAM{ int size,last,lens; int maxs[MAXN*3],trans[MAXN*3][26],parent[MAXN*3],minmatch[MAXN*3]; int Newnode(int a,int b){ ++size; maxs[size]=a; minmatch[size]=INF; memcpy(trans[size],trans[b],sizeof(trans[b])); return size; } void Extend(int x){ static int p,np,q,nq; p=last; last=np=Newnode(maxs[p]+1,0); for(;p&&!trans[p][x];p=parent[p]) trans[p][x]=np; if(!p) parent[np]=1; else{ q=trans[p][x]; if(maxs[p]+1!=maxs[q]){ nq=Newnode(maxs[p]+1,q); parent[nq]=parent[q]; parent[q]=parent[np]=nq; for(;p&&trans[p][x]==q;p=parent[p]) trans[p][x]=nq; } else parent[np]=q; } } void Build(char *S){ memset(trans[0],0,sizeof(trans[0])); size=0; last=Newnode(0,0); lens=strlen(S); for(int i=0;i<lens;i++) Extend(S[i]-‘a‘); } void Update(int *val){ static int tmp[MAXN],order[MAXN*3]; memset(tmp,0,sizeof(tmp)); for(int p=1;p<=size;p++) tmp[maxs[p]]++; for(int i=1;i<=lens;i++) tmp[i]+=tmp[i-1]; for(int p=1;p<=size;p++) order[tmp[maxs[p]]--]=p; for(int i=size,p;i;i--) p=order[i],val[parent[p]]=max(val[parent[p]],val[p]); } void Match(char *T){ static int val[MAXN*3],p,i,len,now; for(p=1;p<=size;p++) val[p]=0; p=1; i=0; now=0; len=strlen(T); while(i<len){ if(!p) p=1,now=0,i++; else if(!trans[p][T[i]-‘a‘]) p=parent[p],now=maxs[p]; else now++,p=trans[p][T[i]-‘a‘],i++; val[p]=max(val[p],now); } Update(val); for(p=1;p<=size;p++) minmatch[p]=min(minmatch[p],val[p]); } }SUF; int main(){ static char S[MAXN]; scanf("%s",S); SUF.Build(S); while(~scanf("%s",S)) SUF.Match(S); int ans=0; for(int p=1;p<=SUF.size;p++) ans=max(ans,min(SUF.minmatch[p],SUF.maxs[p])); printf("%d\n",ans); return 0; }