HNUC-2330 Casino-算法Manacher最长回文子串

原题:Casino

题目描述

Dalia is the assistant director of the fundraising team in the ACPC. She is facing a difficult time this year, there’s a huge lack of sponsors! And now we are facing the danger of not being able to provide the teams with balloons, T-shirts or even name-tags.
Dalia knows it is too late to get a sponsor, actually too late to do anything. But she doesn’t simply give up; she decided that her only hope is to gamble. She will go to a casino where they just invented a new game; she thinks she might have a more promising chance if she plays that game.
The game is very simple, the dealer puts a long string of cards on the table in front of Dalia and she is required to point out palindromes longer than one character (words that are read backward the same as forward) of maximum length (a maximum length palindrome is a palindrome that no other palindrome exists in the string with greater length). So if the maximum length of palindrome in a string is X>1, print all palindromes of length X in the string.

输入

Input will start with T number of test cases. Each test case will consist of 1 line that contains a non-empty string S of lower case English letters no longer than 1000 characters.

输出

For each test case, print a line containing the case number as shown in the sample then print the palindromes each on a line by itself, in the order of their occurrence in S from right to left.

样例输入

2
abcba
abba

样例输出

Case #1:
abcba
Case #2:
abba


Manacher算法求解即可。

#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int len, p[2010];//由于插入字符处理,数组要开至少要开2003=1000*2+2('@','#')+1('\0')
char str[2010], newstr[2010];
int k[1001];
int cas=1;

void change()//插入"#",开头多插入另一个字符"@",防止p[i]越界 
{  
	int i;
	newstr[0] = '@';
	newstr[1] = '#';
	for (i = 0; i < len; i++){
	 newstr[2*i + 2] = str[i];
	 newstr[2*i + 3] = '#';
	}
	newstr[2*len + 2] = '#';
	newstr[2*len + 3] = '\0';
	return ;
}

void Manacher()
{
	int i, j,m, id, maxid = 0, ans = 1;
	len = 2 * len + 2;
	for (i = 1; i < len; i++){//Manacher算法 
		if (maxid > i){
			p[i] = min(p[2*id - i], maxid - i);
		}
		else{
			p[i] = 1;
		}
		while (newstr[i+p[i]] == newstr[i-p[i]])
			p[i]++;
		if (p[i] + i > maxid){
			maxid = p[i] + i;
			id = i;
		}
		if (ans < p[i]) {
			ans = p[i];
		}
	}
	if(ans-1==1){
		cout <<"Case #"<< cas++ <<":"<<endl;
		return ;//没有回文子串时直接返回 
	}
	for(i=1,m=0;i<len;i++){
		if(p[i]==ans){
			k[m]=i;
			m++;
		}
	}//若有一个或多个最长回文子串,记录每一个的中心id 
	cout <<"Case #"<< cas++ <<":"<<endl;
	for(int l=m-1;l>=0;l--){
		for (i = k[l]-p[k[l]]+1, j = 0; i < k[l] + p[k[l]]-1; i++){
			if (newstr[i] != '#'){
				str[j] = newstr[i];
				j++;
			}
		}
	str[j] = '\0';
	cout << str <<endl;
	}//题目要求,多个最长回文子串从右至左输出 
	
	
	return ;  
}  
  
  
int main(){
	int T;
	scanf("%d",&T);
	while (T--){
		scanf("%s", &str);
    	len = strlen(str);
        change();
        Manacher();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值