牛客网 小A的回文串 manachar模板

小A的回文串

链接:https://ac.nowcoder.com/acm/contest/549/B
来源:牛客网
 

小A的回文串

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的。所以小A只想知道给定的一个字符串的最大回文子串是多少,但是小A对这个结果并不是非常满意。现在小A可以对这个字符串做一些改动,他可以把这个字符串最前面的某一段连续的字符(不改变顺序)移动到原先字符串的末尾。那么请问小A通过这样的操作之后(也可以选择不移动)能够得到最大回文子串的长度是多少。

输入描述:

一行一个字符串表示给定的字符串S一行一个字符串表示给定的字符串S

输出描述:

一行输出一个整数,表示通过这样的操作后可以得到最大回文子串的长度。

题解:将输入的字符串s分成两段调换顺序赋到字符串ss中,利用manachar算法求出最长回文串长度,取各种分段情况回文串长度最大值。

#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
char s[50155],ss[50155];
int p[50155];
void init(int lens){
        for(int i=lens;i>=0;i--){
                ss[2*i+1]='&';
                ss[2*i]=ss[i-1];
        }
        ss[0]='@';
        //@&.&.&...&
}
int manachar(char *s,int len){
        int id=0,mx=0,ans=-99999999;
        memset(p,0,sizeof(p));
        for(int i=0;i<len;i++){
                if(i<mx)
                        p[i]=min(p[2*id-i],mx-i);
                else
                        p[i]=1;
                while(ss[i+p[i]]==ss[i-p[i]])
                                p[i]++;
                if(i+p[i]>mx)
                        mx=i+p[i],id=i;
                ans=max(ans,p[i]-1);
        }
        return ans;
}
int main(){
        int len,lens,mx;
        while(~scanf("%s",s)){
                mx=-99999999;
                len=strlen(s);
                memset(ss,0,sizeof(ss));//不能漏,不然会受上一个数据影响
                for(int i=0;i<len;i++){
                        strcpy(ss,s+i);//将i和i以后的串赋值给ss
                        lens=strlen(ss);
                        for(int j=0;j<i;j++)
                                ss[lens++]=s[j];//i之前的串加到ss后面
                        init(lens);//初始化消除字符奇偶数量的影响
                        mx=max(manachar(ss,2*lens+1),mx);
                }
                printf("%d\n",mx);
        }
        return 0;
}

 

posted @ 2019-04-27 21:14  aeipyuan  阅读(122)  评论(0编辑  收藏  举报