天天看点

【manacher算法】POJ 3974 Palindrome

题目链接:http://poj.org/problem?id=3974

题目大意:给定字符串S,求出最长的回文字串长度

用manacher算法可以在O(n)的复杂度求出回文字串长度

manacher算法详解:http://blog.csdn.net/xingyeyongheng/article/details/9310555

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 1000100

int p[N*2+1];//以i为中心的(包含i这个字符)回文串半径长
char s[N*2+1];

void init(char *s,int len){
	int i;
	//在每个相邻的字符之间插入一个分隔符,把奇数长度回文串与偶数长度回文串统一考虑
	for(i=len;i>=0;--i){
		s[i+i+2]=s[i];
		s[i+i+1]='#';
	}
	//插入了len+1个'#',最终的s长度是1~len+len+1即2*len+1,首尾s[0]和s[2*len+2]要插入不同的字符
	s[0]='*';//s[0]='*',s[len+len+2]='\0',防止在while时p[i]越界

	//aba->*#a#b#a#\0
	
}

int manacher(char *s,int len){
	int i;
	int maxlen=0,id=0;
	for(i=1;i<2*len+1;++i){
		if(p[id]+id>i)
			p[i]=min(p[id-(i-id)],id+p[id]-i);
		else
			p[i]=1;

		while(s[i-p[i]]==s[i+p[i]]) p[i]++;

		if(id+p[id]<i+p[i])
			id=i;
		maxlen=max(maxlen,p[i]);
	}
	return maxlen-1;
	//aba->*#a#b#a#\0
	//maxlen=p[4]=4;
}

int main(){
	int cas=1;
	while(scanf("%s",&s)!=EOF&&s[0]!='E'){
		int len=strlen(s);
		int ans=0;
		init(s,len);
		ans=manacher(s,len);
		printf("Case %d: %d\n",cas++,ans);
	}
	return 0;
}