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
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
题意:
判断是否能将字符串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");
}
}

浙公网安备 33010602011771号