题解:
后缀数组
求一下最长公共字串
代码:
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int N=2000200; char s1[N],m,n,s2[N],ss[N]; int height[N],str[N],sa[N],Log[N],best[23][N],rank[N],c[N],t1[N],t2[N]; void da(int *str,int n,int m) { int *x=t1,*y=t2; for (int i=0;i<m;i++)c[i]=0; for (int i=0;i<n;i++)c[x[i]=str[i]]++; for (int i=1;i<m;i++)c[i]+=c[i-1]; for (int i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for (int k=1;k<=n;k<<=1) { int p=0; for (int i=n-k;i<n;i++)y[p++]=i; for (int i=0;i<n;i++) if (sa[i]>=k)y[p++]=sa[i]-k; for (int i=0;i<m;i++)c[i]=0; for (int i=0;i<n;i++)c[x[y[i]]]++; for (int i=1;i<m;i++)c[i]+=c[i-1]; for (int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for (int i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if (p>=n)break; m=p; } } void calheight(int *str,int n) { int j,k=0; for (int i=0;i<=n;i++)rank[sa[i]]=i; for (int i=0;i<n;i++) { if (k)k--; j=sa[rank[i]-1]; while (str[i+k]==str[j+k])k++; height[rank[i]]=k; } } void init(int n) { Log[0]=-1; for (int i=1;i<=n;i++)Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1; for (int i=1;i<=n;i++)best[0][i]=height[i]; for (int i=1;i<=Log[n];i++) for (int j=1;j<=n;j++)best[i][j]=min(best[i-1][j],best[i-1][j+(1<<(i-1))]); } int lcp(int a,int b) { a=rank[a]; b=rank[b]; if (a>b)swap(a,b); a++; int t=Log[b-a+1]; return min(best[t][a],best[t][b-(1<<t)+1]); } int main() { while (~scanf("%d",&m)) { scanf("%s%s",s1,s2); int l1=strlen(s1); int l2=strlen(s2); int len=0; for (int i=0;i<l1;i++)str[len++]=s1[i]; str[len++]=1; for (int i=0;i<l2;i++)str[len++]=s2[i]; str[len]=0; da(str,len+1,300); calheight(str,len); int be,ans=0; for (int i=1;i<=len;i++) { if ((sa[i]<l1&&sa[i-1]>l1)||(sa[i]>l1&&sa[i-1]<l1)) if (ans<height[i])ans=height[i],be=sa[i]; } for (int i=be;i<be+ans;i++)putchar(str[i]); puts(""); } return 0; }