后缀数组三·重复旋律3
#1415 : 后缀数组三·重复旋律3
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。小Hi在练习过很多曲子以后发现很多作品中的旋律有共同的部分。
旋律是一段连续的数列,如果同一段旋律在作品A和作品B中同时出现过,这段旋律就是A和B共同的部分,比如在abab 在 bababab 和 cabacababc 中都出现过。小Hi想知道两部作品的共同旋律最长是多少?
输入
共两行。一行一个仅包含小写字母的字符串。字符串长度不超过 100000。
输出
一行一个整数,表示答案。
- 样例输入
-
abcdefg abacabca
- 样例输出
-
3
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<cmath> #include <bits/stdc++.h> #include<vector> typedef long long ll; const int maxn=2e6+6; using namespace std; typedef std::pair<ll,ll> pll; typedef std::string str; int sa[maxn],rk[maxn],tp[maxn],height[maxn]; char s1[maxn],s2[maxn]; int ton[maxn],e[maxn],mx,n; inline void rsort(){ for(register int i=0;i<mx;++i)ton[i]=0; for(register int i=1;i<=n;++i)ton[rk[i]]++; for(register int i=1;i<=mx;++i)ton[i]=ton[i]+ton[i-1]; for(register int i=n;i>=1;--i)sa[ton[rk[tp[i]]]--]=tp[i]; } inline void solve(){ for(register int i=1;i<=n;++i)rk[i]=e[i],tp[i]=i; rsort(); for(register int w=1,p=0;w<=n&&p<n;w*=2,mx=p){ p=0; for(register int i=n-w+1;i<=n;++i){ tp[++p]=i; } for(register int i=1;i<=n;++i){ if(sa[i]>w){ tp[++p]=sa[i]-w; } } rsort(); swap(rk,tp); rk[sa[1]]=p=1; for(register int i=2;i<=n;++i){ rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p; } if(p>=n)break; } int k=0; for(register int i=1;i<=n;++i){ rk[sa[i]]=i; } for(register int i=1;i<=n;++i){ if(k)k--; else k=0; int j=sa[rk[i]-1]; while(e[i+k]==e[j+k])++k; height[rk[i]]=k; } } int main() { //freopen("1.txt","r",stdin); scanf("%s%s",s1+1,s2+1); int len1=strlen(s1+1),len2=strlen(s2+1); n=len1+len2+1; for(register int i=1;i<=len1;++i){ e[i]=s1[i]-'a'+1; mx=max(mx,e[i]); } for(register int i=1;i<=len2;++i){ e[i+len1+1]=s2[i]-'a'+1; mx=max(mx,e[i+len1+1]); } e[len1+1]=300; mx=max(mx,300); solve(); int res=0; // for(register int i=1;i<=n;++i){ // printf("debug rk[%d] = %d sa[%d] = %d height[%d] = %d\n",i,rk[i],i,sa[i],i,height[i]); // } for(register int i=2;i<=n;++i){ if(sa[i]<=len1&&sa[i-1]<=len1)continue; if(sa[i]>len1&&sa[i-1]>len1)continue; res=max(res,height[i]); } printf("%d\n",res); return 0; } /* * abcdefg abacabca */