Palindrome

问题描述

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

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;
}

猜你喜欢

转载自blog.csdn.net/yx970326/article/details/80034516