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;
}

 

posted @ 2018-03-25 23:31  ws_zzy  阅读(225)  评论(0编辑  收藏  举报