程帅霞

不断受挫,不停起身,不断追寻,不止AC~~

导航

马拉车

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int M=1000010;
int p[M];                     ///记录以i为中心的最大回文半径
char a[M];                    ///原始字符串
char b[M];                    ///优化字符串
void manacher()
{
    ///第一阶段:字符串优化
    int i,k,l;
    l=strlen(a);              ///原始字符串长度
    b[0]='$';                 ///防止出界
    b[1]='#';                 ///加入输入字符串未出现的字符
                              ///目的:使偶数字符串变为奇数字符串
    k=2;                      ///优化字符长度记录
    for(i=0;i<l;i++)
    {
        b[k++]=a[i];
        b[k++]='#';
    }
    b[k]=0;                   ///目的:设置边界
    ///第二阶段:寻找最大回文串的长度
    int id=0,mx=0;            ///mx为以id为中心的最右边的边界:mx=id+p[id];
    int len=0;                ///记录最大回文串长度
    for(i=1;i<k;i++)
    {
        if(i<mx)              ///判断:如果i在id的右边界内
        {
            p[i]=min(p[2*id-i],mx-i);
            ///核心:2*id-i是i关于id的对称点,设为j,如果对称点p[j]<=mx-i,说明未出界,p[i]=p[j];
            /// 如果对称点p[j]>mx-i,说明出界,界外的字符未知,需要一个一个判断,此时p[i]!=p[j];
        }
        else
            p[i]=1;            ///如果i出id的右边界,则初始回文半径为1
        while(b[i+p[i]]==b[i-p[i]]) ///不需要判断边界,因为左有$,右有0
            p[i]++;                 ///判断界外关于i对称字符是否相等,相等回文半径长度增加
        if(p[i]>mx-i)          ///判断i的右边界和id右边界的大小
        {
            mx=i+p[i];           ///i的右边界大,更新边界mx和中心点id
            id=i;
        }
        if(p[i]-1>len)           ///p[i]-1为回文串的长度
            len=p[i]-1;          ///更新最大长度
    }
    printf("%d\n",len);

}
int main()
{
    while(~scanf("%s",a))
        manacher();
    return 0;
}
View Code

 

posted on 2021-01-23 13:59  程帅霞  阅读(63)  评论(0编辑  收藏  举报