NCSTOJ: [算法竞赛进阶指南]Palindrome

N : [算法竞赛进阶指南]Palindrome
Time Limit:2 Sec Memory Limit:128 MiB
Back Submit Edit

Description
[poj 3974]

如果一个字符串正着读和倒着读是一样的,则称它是回文的。

给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

Input
输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。

输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。

Output
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

每个输出占一行。

Sample Input
abcbabcbabcba
abacacbaaaab
END
Sample Output
Case 1: 13
Case 2: 6

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
using ull=unsigned long long;
const int maxn=2000010;
const int P=13331;
ull hl[maxn],hr[maxn],hp[maxn];//hl和hr分别是正序和逆序保存字符串哈希值的数组
char str[maxn],str2[maxn];//str2为字符串预处理之后的数组
ull HL(int pos,int r)
{//用于在正序中获得pos到pos+r之间的哈希值 
	return hl[pos+r]-hl[pos]*hp[r];
}
ull HR(int pos,int r)
{//用于在逆序中获得pos-r到pos之间的哈希值 
	return hr[pos-r]-hr[pos]*hp[r];
}


int main(){
	//freopen("qwe.txt","r",stdin);
	int t=0;
	while(scanf("%s",str+1),strcmp(str+1,"END"))
	{
		cout<<"Case "<<++t<<": ";
		
	int n=strlen(str+1);	
	int cur=1;
	str2[1]='#';
	for(int i=1;i<=n;i++)
	{//对字符串进行预处理 
		str2[++cur]=str[i];
		str2[++cur]='#';
	}
	n=cur;
	hl[0]=0;
	hp[0]=1;
	for(int i=1;i<=n;i++)
	{//构建正序字符串哈希表 
		hl[i]=hl[i-1]*P+(str2[i]-'a'+1);
		hp[i]=hp[i-1]*P;
	}
	hr[n+1]=0;
	for(int i=n;i>=1;i--)
	{//构建逆序字符串哈希值
	//注意逆序字符串哈希值是从字符串结尾开始循环计算式的 
		hr[i]=hr[i+1]*P+(str2[i]-'a'+1);
	}
	
	int r=1;
	for(int i=1;i<=n;i++)
	{
		if(i-r<0||i+r>n)break;//越界时表示已经在上次循环计算中得到最大的对称字符串
        if(HL(i,r)!=HR(i,r))continue;
		//用于判断正序逆序的哈希值是否相同
	    while(str2[i-r-1]==str2[i+r+1]&&i+r+1<=n&&i-r-1>=1)
	    r++;//在有上句判断的基础上本语句是在扩充对称字符串范围的作用 
	    
	}
	cout<<r<<endl;
	}
	
	return 0;
	
} 
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值