题链:
http://poj.org/problem?id=2774
题解:
后缀自动机
使用后缀自动机匹配,思路如下:
即如果当前的x字符匹配失败了,就可以从当前已经匹配的串的后缀去继续匹配。
然后不难发现,对于失配的状态s的parent[s]恰好是可能能够继续匹配x且Right集合是最小的包含s的Right集合(即允许的合法长度除了s外是最长的)的状态。
所以就沿着parent指针向上跳,直到trans[*][x]存在或者到了0号节点。
代码:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 250005 using namespace std; struct SAM{ int size,last; int maxs[MAXN*5],trans[MAXN*5][26],parent[MAXN*5]; int Newnode(int a,int b){ maxs[size]=a; 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=1; last=Newnode(0,0); for(int i=0;S[i];i++) Extend(S[i]-‘a‘); } int Match(char *T){ int p=1,i=0,ans=0,now=0,len=strlen(T); while(i<len){ if(p&&!trans[p][T[i]-‘a‘]){ ans=max(ans,min(now,maxs[p])); p=parent[p]; now=maxs[p]; } else if(p) now++,p=trans[p][T[i]-‘a‘],i++; else i++,p=1; } return max(ans,min(now,maxs[p])); } }SUF; int main(){ char S[MAXN]; scanf("%s",S); SUF.Build(S); scanf("%s",S); int ans=SUF.Match(S); printf("%d\n",ans); return 0; }