poj2774 Long Long Message(后缀数组)
只需要把两个串拼接起来,之后求一下后缀数组求可覆盖最长重复子串模板即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=3e5+10; string a,b; int id[N],rk[N],sa[N],h[N],cnt[N]; int od[N],px[N]; bool cmp(int x,int y,int w){ return od[x]==od[y]&&od[x+w]==od[y+w]; } int main(){ ios::sync_with_stdio(false); cin>>a>>b; int sign; a=" "+a+"A"; sign=a.size()-1; a+=b; // cout<<sign<<endl; int i; int n=(int)a.size()-1; int m=max(n,300); for(i=1;i<=n;i++) cnt[rk[i]=a[i]]++; for(i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(i=n;i>=1;i--) sa[cnt[rk[i]]--]=i; int p; for(int w=1,p=0;w<n;w<<=1,m=p){ for(p=0,i=n;i>n-w;i--){ id[++p]=i; } for(i=1;i<=n;i++){ if(sa[i]>w){ id[++p]=sa[i]-w; } } memset(cnt,0,sizeof cnt); for(i=1;i<=n;i++) cnt[px[i]=rk[id[i]]]++; for(i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(i=n;i>=1;i--) sa[cnt[px[i]]--]=id[i]; memcpy(od,rk,sizeof rk); for(p=0,i=1;i<=n;i++){ rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p; } } for(i=1;i<=n;i++){ if(rk[i]==1) continue; int x=max(h[rk[i-1]]-1,0); while(i+x<=n&&a[i+x]==a[sa[rk[i]-1]+x]) x++; h[rk[i]]=x; } int ans=0; for(i=2;i<=n;i++){ int x=sa[i-1]; int y=sa[i]; if((x<=sign&&y>sign)||(x>sign&&y<=sign)){ ans=max(ans,h[i]); } } cout<<ans<<endl; return 0; }
没有人不辛苦,只有人不喊疼