刚学manacher,76求助

P4287 [SHOI2011] 双倍回文

ycw123 @ 2021-10-04 19:26:06

#include<bits/stdc++.h>
using namespace std;
int n,r,c,p,m,ans;
char ch[500010];
int a[2200010],len=2,b[2200010];//a:处理后字符串 b:半径数组 
int getb(int x,int q){//暴力计算半径 
    int k;
    for(k=q;x-k>=1&&x+k<=len;k++){
        if(a[x-k]!=a[x+k]) return k;
    }
    return k;
}
int main(){
    cin>>n;
    cin>>ch;
    for(int i=0;i<n;i++,len+=2){
        a[len-1]=-1; 
        a[len]=ch[i];
    }
    len--;
    a[len]=-1;
    //manachar 
    for(int i=1;i<=len;i++){
        if(i>r) {
            b[i]=getb(i,1);
            if(r<i+b[i]-1){
                r=i+b[i]-1;
                c=i;
            }
        }
        else{
            int j=2*c-i;//j:i的对称点 
            int lj=j-b[j]+1;//lj:以j为中心的最大回文串左端点 
            if(lj>2*c-r) b[i]=b[j];
            else if(lj==2*c-r){
                b[i]=getb(i,r+1-i);
                if(r<i+b[i]-1){
                    r=i+b[i]-1;
                    c=i;
                }
            }else b[i]=r-i+1;
        }
        //双倍回文判断: 1.对称中心是特殊字符 2.串长是4的倍数 3.左回文串的半径恰好是四分之一串长 
        if(a[i]==-1&&(b[i]-1)%4==0&&((2*i-b[i]+1)/2+b[(2*i-b[i]+1)/2])==i+1) ans=max(ans,b[i]);
    }
    if(ans)
    cout<<ans-1;
    else cout<<0;
    return 0;
}

|