求解为什么这样做不对

P4287 [SHOI2011] 双倍回文

火羽白日生 @ 2021-05-24 08:16:59

rt

思路就是求出以 i 为左右端点的最长回文串长度 l_i,r_i,然后枚举每个断点#判断

但是 WA 了两个点

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rint register int

using namespace std;

inline int read(){
    int w=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){w=(w<<3)+(w<<1)+(ch^48); ch=getchar();}
    return w*f;
}

const int maxn=5e5+5;
const ull base=13131;

int n,ans;
ull pw[maxn<<1],h[maxn<<1];
char s[maxn],str[maxn<<1];
namespace Manacher{
    int p[maxn<<1],l[maxn<<1],r[maxn<<1],cnt,mid,R;
    inline void rebuild(){
        str[++cnt]='~',str[++cnt]='#';
        for(int i=1;i<=n;i++) str[++cnt]=s[i],str[++cnt]='#';
        str[++cnt]='@';
        n=cnt-1;
    }
    inline void manacher(){
        for(int i=1;i<=n;i++){
            if(i<=R) p[i]=min(p[mid*2-i],R-i+1);
            else p[i]=1;
            while(str[i-p[i]]==str[i+p[i]]) p[i]++;
            if(i+p[i]>R) R=i+p[i]-1,mid=i;
            l[i-p[i]+1]=max(l[i-p[i]+1],p[i]-1);
            r[i+p[i]-1]=max(r[i+p[i]-1],p[i]-1);
        }
    }
}using namespace Manacher;
inline void init(){
    pw[0]=1; h[0]=0;
    for(int i=1;i<maxn*2;i++) pw[i]=pw[i-1]*base;
}
inline ull gethash(int l,int r){
    return (h[r]-h[l-1]*pw[r-l+1]);
}

int main(){
    n=read();
    scanf("%s",s+1);
    rebuild(); manacher(); init();
    for(int i=1;i<=n;i++) h[i]=h[i-1]*base+(ull)(str[i]+1);
    for(int i=1;i<=n;i+=2) l[i]=max(l[i],l[i-2]-2);
    for(int i=n;i>=1;i-=2) r[i]=max(r[i],r[i+2]-2);
    for(int i=2;i<=n;i+=2) 
        if(l[i] && r[i] && l[i]==r[i] && l[i]%2==0 && r[i]%2==0 && gethash(i+1,i+2*l[i]-1)==gethash(i-2*r[i]+1,i-1))
                ans=max(ans,l[i]+r[i]);
    printf("%d\n",ans);
    return 0;
}

by w33z8kqrqk8zzzx33 @ 2021-05-24 11:40:46

ull 哈希不正确,可以直接构造卡,必须要取模


|