BZOJ 4755:[Jsoi2016]扭动的回文串
题解:
先求每个串的最长回文串
然后两个串的一定是一个串的某一个最长回文串向两边扩展
用后缀数组求
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=800009; int n,len; int ans=0; char A[maxn]; int Atl[maxn],Atr[maxn]; char B[maxn]; int Btl[maxn],Btr[maxn]; char s[maxn]; int c[maxn],sa[maxn]; int t1[maxn],t2[maxn]; void BuildSA(int n,int m){ int *x=t1,*y=t2; for(int i=1;i<=m;++i)c[i]=0; for(int i=1;i<=n;++i)c[x[i]=s[i]]++; for(int i=2;i<=m;++i)c[i]+=c[i-1]; for(int i=n;i>=1;--i)sa[c[x[i]]--]=i; for(int k=1;k<n;k<<=1){ int p=0; for(int i=n-k+1;i<=n;++i)y[++p]=i; for(int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k; for(int i=1;i<=m;++i)c[i]=0; for(int i=1;i<=n;++i)c[x[y[i]]]++; for(int i=2;i<=m;++i)c[i]+=c[i-1]; for(int i=n;i>=1;--i)sa[c[x[y[i]]]--]=y[i]; swap(x,y); x[sa[1]]=p=1; for(int i=2;i<=n;++i){ int a=sa[i],b=sa[i-1]; if((y[a]==y[b])&&(y[a+k]==y[b+k]))x[sa[i]]=p; else x[sa[i]]=++p; } if(p>=n)break; m=p; } } int rk[maxn],ht[maxn]; void GetHeight(int n){ for(int i=1;i<=n;++i)rk[sa[i]]=i; int k=0; for(int i=1;i<=n;++i){ if(k)k--; if(rk[i]==1)continue; int j=sa[rk[i]-1]; while(s[i+k]==s[j+k])++k; ht[rk[i]]=k; } } int f[maxn][20]; void STinit(int n){ for(int i=1;i<=n;++i)f[i][0]=ht[i]; for(int j=1;j<=19;++j){ for(int i=1;i+(1<<j)-1<=n;++i){ f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } } int ds[maxn]; int Querymin(int l,int r){ int k=ds[r-l+1]; return min(f[l][k],f[r-(1<<k)+1][k]); } int main(){ scanf("%d",&n); scanf("%s",A+1); s[len=1]='*'; for(int i=1;i<=n;++i){ s[++len]=A[i];s[++len]='*'; } for(int i=1;i<=n*2+1;++i)A[i]=s[i]; scanf("%s",B+1); s[len=1]='*'; for(int i=1;i<=n;++i){ s[++len]=B[i];s[++len]='*'; } for(int i=1;i<=n*2+1;++i)B[i]=s[i]; n=n*2+1; for(int i=1;i<=n+n;++i)ds[i]=(int)log2(i+0.5); memset(s,0,sizeof(s)); for(int i=1;i<=n;++i)s[i]=s[n*2-i+1]=A[i]; BuildSA(n+n,200); GetHeight(n+n); STinit(n+n); for(int i=1;i<=n;++i){ int x=i,y=2*n-i+1; x=rk[x];y=rk[y]; if(x>y)swap(x,y); len=Querymin(x+1,y); Atl[i]=i-len+1; Atr[i]=i+len-1; ans=max(ans,len*2-1); } memset(s,0,sizeof(s)); for(int i=1;i<=n;++i)s[i]=s[n*2-i+1]=B[i]; BuildSA(n+n,200); GetHeight(n+n); STinit(n+n); for(int i=1;i<=n;++i){ int x=i,y=2*n-i+1; x=rk[x];y=rk[y]; if(x>y)swap(x,y); len=Querymin(x+1,y); len=min(len,min(i,n-i+1)); Btl[i]=i-len+1; Btr[i]=i+len-1; ans=max(ans,len*2-1); } for(int i=1;i<=n;++i)s[n-i+1]=A[i]; for(int i=1;i<=n;++i)s[i+n]=B[i]; BuildSA(n+n,200); GetHeight(n+n); STinit(n+n); // cout<<(A+1)<<endl; // cout<<(B+1)<<endl; // cout<<(s+1)<<endl; for(int i=1;i<=n;++i){ int l=Atl[i],r=Atr[i]; if((l==1)||(r==n))continue; int x=n-l+2,y=r+n-1; x=rk[x];y=rk[y]; if(x>y)swap(x,y); len=Querymin(x+1,y); len=min(len,min(l,n-r+2)); ans=max(ans,len*2+(r-l+1)); } for(int i=1;i<=n;++i){ int l=Btl[i],r=Btr[i]; if((l==1)||(r==n))continue; int x=n-l,y=r+n+1; x=rk[x];y=rk[y]; if(x>y)swap(x,y); len=Querymin(x+1,y); len=min(len,min(l+1,n-r)); ans=max(ans,len*2+(r-l+1)); } cout<<ans/2<<endl; return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!