UVA 1470 Castting Spells(manacher)

来源:互联网 发布:编程计算阶乘的和 编辑:程序博客网 时间:2024/05/17 02:41

这题很容易看出来是个判断回文,manacher板子直接上了,但是最后被细节卡了= =。

细节1:因为回文串ww^r个数肯定是偶数,所以枚举时,只能枚举‘#’的位置。

细节2:因为细节1说了,'#'左右两边字符串长度一定是偶数,那么如果当前位置的v=p[i]-1必须为偶数,而且v时整个字符串的长度,所以膜4必须为0,如果不符合条件,那么只能减小回文的长度,增大是肯定不可能的。

细节3:当v满足以上两个细节之后,那么可以判断ww^r是否是回文了,判断方法是左右两边字符串的中心的回文长度可以覆盖到总的字符串的中点,如果不可以,那么也只能减小左右两边字符串的长度(不能增大,否则总字符串不满足回文),那么左边的中心需要向右移到下一个‘#’,右边向左移动,那么就是v-4。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=600000+5;int p[maxn];char s[maxn];void manacher(int len){    for(int i=len;i>=0;i--){        s[i+i+2]=s[i];        s[i+i+1]='#';    }    int pos=0;    for(int i=2;i<2*len+1;i++){        if(p[pos]+pos>i) p[i]=min(p[pos*2-i],p[pos]+pos-i);        else p[i]=1;        while(s[i-p[i]]==s[i+p[i]]) p[i]++;        if(i+p[i]>pos+p[pos]) pos=i;    }}void solve(int len){    int ans=0;    for(int i=1;i<2*len+1;i+=2)    {        int v=p[i]-1;        while(v%4!=0) v--;        for(;v>ans;v-=4)            if(p[i+v/2]-1>=v/2&&p[i-v/2]-1>=v/2) {ans=v;break;}    }    printf("%d\n",ans);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",s);        int len=(int)strlen(s);        manacher(len);        solve(len);    }    return 0;}


0 0