Description
多组数据,每组给出两个小写字母组成的字符串,求两个字符串的最长公共子串,如有多个按字典序顺序输出,如没有输出 No common sequence.
,每两组数据间输出一个空行,最后一组数据后不应输出空行。
Solution
将两个字符串用分隔符连在一起,求出SA
求出height的最大值,要求这个最大值对应的两个串位于分隔符两侧
所有相同的答案在height数组中都是连续的,遇到相同就可以跳过
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int t,len1,len2,sa[615],buc[615],rk[615],x[615],y[615],height[615],m=131,n,ans; char S[305],T[305],s[615]; inline int read(){ int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } void getsa(){ m=131; for(int i=1;i<=m;i++)buc[i]=0; for(int i=1;i<=n;i++)++buc[x[i]=s[i]]; for(int i=2;i<=m;i++)buc[i]+=buc[i-1]; for(int i=n;i;i--)sa[buc[x[i]]--]=i; for(int k=1;k<=n;k<<=1){ int num=0; for(int i=n-k+1;i<=n;i++)y[++num]=i; for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k; for(int i=1;i<=m;i++)buc[i]=0; for(int i=1;i<=n;i++)++buc[x[i]]; for(int i=2;i<=m;i++)buc[i]+=buc[i-1]; for(int i=n;i;i--)sa[buc[x[y[i]]]--]=y[i],y[i]=0; swap(x,y),x[sa[1]]=1,num=1; for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num; if(num==n)break; m=num; } } void getheight(){ int k=0; for(int i=1;i<=n;i++)rk[sa[i]]=i; for(int i=1;i<=n;i++){ if(rk[i]==1)continue; if(k)--k; int j=sa[rk[i]-1]; while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k])++k; height[rk[i]]=k; } } int main(){ while(scanf("%s%s",S+1,T+1)!=EOF){ ans=0,++t,len1=strlen(S+1),len2=strlen(T+1),s[len1+1]='$'; if(t>1)putchar(10); for(int i=1;i<=len1;i++)s[i]=S[i]; for(int i=1;i<=len2;i++)s[i+len1+1]=T[i]; n=len1+len2+1,getsa(),getheight(); for(int i=2;i<=n;i++)if(sa[i-1]<=len1&&sa[i]>len1+1||sa[i-1]>len1+1&&sa[i]<=len1)ans=max(ans,height[i]); if(!ans){puts("No common sequence.");continue;} for(int i=2;i<=n;i++)if(height[i]==ans){ int j=i,k=i; while(height[j]==ans)++j; for(;k<j;k++)if(sa[k-1]<=len1&&sa[k]>len1+1||sa[k-1]>len1+1&&sa[k]<=len1)break; if(k!=j){ for(int p=sa[k];p<sa[k]+ans;p++)putchar(s[p]); putchar(10); } i=j-1; } } return 0; }