题目描述
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
字符串长度为n
输入输出格式
输入格式:
一行小写英文字符a,b,c...y,z组成的字符串S
输出格式:
一个整数表示答案
输入输出样例
输入样例#1: 复制
aaa
输出样例#1: 复制
3
说明
字符串长度len <= 11000000
这是一个求最长回文子串长度的算法(o(n))
先把=字符串化成#a#b#a#(#a#b#b#a#)的样子 这样的话就不用在意字符串是奇数个还是偶数个了,这样化了之后字符串就变成了奇数 只要按奇数的来考虑就好了。
同时 加上 sum+=r[i]/2; 可以求回文子串的个数
#include<bits/stdc++.h>
using namespace std;
char s[11000005*2],t[11000005];
int r[11000005*2];
int change()
{
int j=2,len=strlen(t);
s[0]='$';//第一个设置为不同的字符 方便结束
s[1]='#';
for(int i=0; i<len; i++)
{
s[j++]=t[i];
s[j++]='#';
}
s[j++]='#';
return j;
}//化成#a#b#a#(#a#b#b#a#)的样子 最后返回字符串的长度
int manacher()
{
int len=change(),maxn=1,mid=1,ans=-1,sum=0;
for(int i=1; i<len; i++)
{
if(i<maxn)//i在maxn左边时
r[i]=min(maxn-i,r[mid*2-i]);
//i关于mid有一个对称点j 因为是对称的 所以r[i]不会比r[j]小,所以可以令起点为r[j(即2*mid-i)]
//又因为r[i]+i<=maxn 所以r[i]<=maxn-i 综合得到这个式子
else//最右边时 无法得知 所以令r[i]=1;
r[i]=1;
while(s[i+r[i]]==s[i-r[i]]) r[i]++;//以i为中心向俩边扩散
if(maxn<i+r[i])//更新最大值
{
mid=i;//中心为mid
maxn=i+r[i];//最右边为maxn
}
ans=max(ans,r[i]-1);//求出最长回文子串的长度(因为要除去$所以要减一)
//sum+=r[i]/2;//加上这一句可以用来求回文子串的个数
}
return ans;
}
int main()
{
scanf("%s",t);
printf("%d\n",manacher());
return 0;
}