题解 P4287 【[SHOI2011]双倍回文】

· · 题解

(难得有次直接讲题

ps:之前有大佬在题解里说了,在枚举mid的时候,并不需要把i-rad[i]+1到i全部找一遍,只用到i-rad[i]+7就ok(没有为什么,因为这是试出来的

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm> 
#define MAXN 4100000
using namespace std;
int rad[MAXN],n;
char s[MAXN],ch[MAXN];
int mr=-1,c;
void find(int x,int y){
    int i=y;
    for(;(x-i)>=0&&(x+i)<=2*n;i++){
        if (s[x-i]!=s[x+i])break;
    }
    rad[x]=i;
}
int main(){
    s[0]='#';
    cin>>n;
    cin>>ch+1;
    for(int i=1;i<=n;i++){
        s[2*i-1]=ch[i];
        s[2*i]='#'; 
    }
    int ans=0;
    memset(rad,0,sizeof(rad));
    for(int i=0;i<=n*2;i++){
        if (i&1)continue;
        if (i>mr) find(i,0);
        else {
            int cl,p2,pl;
            cl=c-(mr-c);
            p2=c-(i-c);
            pl=p2-rad[p2]+1;
            if (pl>cl){
                rad[i]=rad[p2];
            }
            else if (pl<cl){
                rad[i]=mr-i+1;
            }
            else {
                find(i,mr-i+1);
            }
        }
        if (i+rad[i]-1>mr){
            mr=i+rad[i]-1;
            c=i;
        }
        int mid,l;
        for(int j=0;j<=6;j++){
             mid=i-rad[i]+1+j;
             l=mid-(i-mid);
             if (l<0)continue;
             if (l+rad[l]-1>=mid&&mid+rad[mid]-1>=i)ans=max(ans,(rad[i]-j)*2-2);
        } 
    }
    cout<<ans<<endl;
    return 0;
}