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 T�20
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 "); 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 "); else printf("No "); } }