hdu 5340 Three Palindromes(manacher)

Three Palindromes

http://acm.hdu.edu.cn/showproblem.php?pid=5340

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description
Can we divided a given string S into three nonempty palindromes?
 
 
Input
First line contains a single integer T20 which denotes the number of test cases.

For each test case , there is an single line contains a string S which only consist of lowercase English letters.1|s|20000
 
 
Output
For each case, output the "Yes" or "No" in a single line.
 

 

Sample Input
2 abc abaadada
 

 

Sample Output
Yes No
 

 

Source
 

 

Recommend
hujie   |   We have carefully selected several similar problems for you:  6022 6021 6020 6019 6018 
 
题意:
判断是否能将字符串S分成三段非空回文串
因为将整个字符串分为3段,所以字符串要有回文前缀、回文后缀
对原串做一遍manacher
pre[]记录回文前缀的结尾处,suf[]记录回文后缀的开始处
枚举所有前缀结尾处,后缀开始处
这样就可以锁定第二段
如果第二段的终点的回文区间与第三段相接或覆盖,就可以
注:以上均是在经manacher处理后的字符串上进行,即保证串长是奇数
 
可以用bitset优化,01记录是否是回文前缀、后缀
枚举第二段的回文中心,在第二段范围内,若前缀01序列和后缀翻过来的01序列有共同位置为1,则可以
 
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n,len,p[41001];
int pre[40001],suf[40001];
char a[20001],s[41001];
void manacher()
{
	n=0;
	s[n++]='!';
	for(int i=0;i<len;i++)
	{
		s[n++]='#';
		s[n++]=a[i];
	}
	s[n++]='#';
	s[n]='@';
	int id=0,pos=0,x;
	for(int i=1;i<=n;i++)
	{
		if(pos>i) x=min(p[id*2-i],pos-i);
		else x=1;
		while(s[i+x]==s[i-x]) x++;
		if(i+x>pos) 
		{
			pos=i+x; 
			id=i;
		}
		p[i]=x;
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s",a);
		len=strlen(a);	
		if(len<3)
		{
			printf("No\n");
			continue;
		}
		manacher();
		int l=0,r=0;
		for(int i=2;i<n-1;i++)//WA 1 :不能 从1到n ,1、n位置是#,不能算 
		 {
		 	if(i==p[i]) pre[++l]=i+p[i]-1;
		 	if(i+p[i]-1==n-1) suf[++r]=i-p[i]+1;
		 }
		int t1,t2,mid;
		bool ok=false;
		for(int i=1;i<=l;i++)
		{
			for(int j=1;j<=r;j++)
			{
			 	t1=pre[i],t2=suf[j];
			 	t1++;t2--;
			 	if(t1>t2) continue;///////// WA 2
			 	mid=t1+t2>>1;
			 	if(mid+p[mid]-1>=t2) 
			 	{
			 		ok=true;
			 		break;
				}
		 	}
		 	if(ok) break;
		}
		if(ok) printf("Yes\n");
		else printf("No\n");
	}
}

  

posted @ 2017-04-05 16:07  TRTTG  阅读(198)  评论(0编辑  收藏  举报