问题描述
Palindrome
Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you propose an efficient algorithm to find the length of the largest palindrome in a string?"
A string is said to be a palindrome if it reads the same both forwards and backwards, for example "madam" is a palindrome while "acm" is not.
The students recognized that this is a classical problem but couldn't come up with a solution better than iterating over all substrings and checking whether they are palindrome or not, obviously this algorithm is not efficient at all, after a while Andy raised his hand and said "Okay, I've a better algorithm" and before he starts to explain his idea he stopped for a moment and then said "Well, I've an even better algorithm!".
If you think you know Andy's final solution then prove it! Given a string of at most 1000000 characters find and print the length of the largest palindrome inside this string.
Input
Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you propose an efficient algorithm to find the length of the largest palindrome in a string?"
A string is said to be a palindrome if it reads the same both forwards and backwards, for example "madam" is a palindrome while "acm" is not.
The students recognized that this is a classical problem but couldn't come up with a solution better than iterating over all substrings and checking whether they are palindrome or not, obviously this algorithm is not efficient at all, after a while Andy raised his hand and said "Okay, I've a better algorithm" and before he starts to explain his idea he stopped for a moment and then said "Well, I've an even better algorithm!".
If you think you know Andy's final solution then prove it! Given a string of at most 1000000 characters find and print the length of the largest palindrome inside this string.
Input
abcbabcbabcba
abacacbaaaab
END
output
Case 1: 13
Case 2: 6
寻找最长回文序列,考察马拉车算法
code:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000005;
int p[maxn*2];//记录以i为中心的最长回文串的长度
char s[maxn];
char news[maxn*2];//保存改造后的字符串
int newlen;//记录改造后字符串的长度
int Getnew(){//得到一个新的字符串,保存在news数组中,并返回新字符串的长度
int index=0;
int len=strlen(s);//记录字符串长度
news[0]='@';//在头部设置特殊字符,以便后期统计越界
news[1]='#';
newlen=2;
for(int i=0;i<len;i++){
news[newlen++]=s[i];
news[newlen++]='#';
}
news[newlen]='\0';
return newlen;
}
int Manacher(int newlen){
int mx=0;
int id=0;
int ans=0;
for(int i=1;i<newlen;i++){
if(i>mx){//若i已超过之前mx达到的最远距离,此时只好将P[i]置为1,然后乖乖地向两边延伸
p[i]=1;
}
else{//i没有超过mx之前到达的最远距离,所以此时p[i]的值应为p[j]和 mx-i 的最小值(j和i关于id对称,因为当前统计的最长回文序列出现在
//以id为中心,不超过mx的范围内,)
p[i]=min(p[id*2-i],mx-i);
}
while(news[i-p[i]]==news[i+p[i]])p[i]++;//从i点分别向两边延伸,若对称的两个字符相等,则p[i]++
if(p[i]+i>mx){
mx=p[i]+i;
id=i;
}
ans=max(ans,p[i]-1);
}
return ans;
}
int main(){
int i=1;
while(1){
scanf("%s",s);
if(strcmp(s,"END")==0)break;
newlen=Getnew();
int res=Manacher(newlen);
cout<<"Case "<<i<<": "<<res<<endl;
i++;
}
return 0;
}