题:
聪明的计算机科学学生安迪正在上算法课,教授问学生一个简单的问题,“你能提出一个有效的算法来找出字符串中最大回文的长度吗?”
如果一个字符串向前和向后读都是相同的,那么它就被称为回文。例如,“madam”是回文,“acm”不是。
学生们认识到这是一个经典的问题,但是他们无法找到一个比遍历所有子串并检查它们是否是回文的更好的解决方案,显然这个算法根本没有效率,过了一会儿,安迪举起手说:“好吧,我有更好的在他开始解释他的想法之前,他停了一下,然后说:“好吧,我有一个更好的算法!”.
如果你认为你知道安迪的最终解决方案,那就证明它!如果字符串最多为1000000个字符,则查找并打印该字符串中最大回文的长度。
输入
您的程序最多将在30个测试用例上进行测试,每个测试用例本身就以一行最多1000000个小写字符的字符串形式给出。输入被以字符串“end”开头的行终止(为清晰起见,用引号引起来)。
输出
对于输入中的每个测试用例,打印测试用例编号和最大回文的长度。
Sample Input
abcbabcbabcba
abacacbaaaab
END
Sample Output
Case 1: 13
Case 2: 6
题解:
一道最长回文的模板题:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstring>
#include <stdio.h>
char s[2200100],a[1100050];
int len,pos,p[2200100],ans,r;
using namespace std;
void add()
{
s[0]='A';
int i=1,j=0;
while(i<2*len+1)
{
s[i++]='#';
s[i++]=a[j++];
}
s[i++]='#';
len=2*len+2;
}
int Manacher()
{
ans=r=pos=0;
for(int i=0;i<len;i++)
{
if(i<r)
p[i]=min(p[2*pos-i],r-i);
else
p[i]=1;
while(s[i+p[i]]==s[i-p[i]])
p[i]++;
if(i+p[i]>r)
{
r=i+p[i];
pos=i;
}
ans=max(ans,p[i]-1);
}
return ans;
}
int main()
{
int i=0;
while(scanf("%s",a))
{
if(strcmp(a,"END")==0)
{
break;
}
i++;
len=strlen(a);
add();
ans=Manacher();
cout<<"Case "<<i<<": ";
cout<<ans<<endl;
}
}