小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
",mx);
}
return 0;
}