您的位置:首页 > 其它

BestCoder Round #49 Three Palindromes 即 hdu5340 (manacher算法)

2015-08-06 00:44 369 查看


Three Palindromes

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

Total Submission(s): 1132    Accepted Submission(s): 370

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

 

Output

For each case, output the "Yes" or "No" in a single line.

 

Sample Input

2
abc
abaadada

 

Sample Output

Yes
No

 

Source

BestCoder Round #49 ($)

 

Recommend

hujie   |   We have carefully selected several similar problems for you:  5352 5351 5350 5349 5348 

 
解析:摘自FancyCoder
/*

对原串前缀和后缀作一个01标记pre[i],suf[i]表示1-i和i-n能否能形成回文。记以i为中心的回文半径为r(i)。

这些都可以在O(N)时间内求出。也可以使用Hash+二分等方法O(NlogN)内求出。

我们考虑中间一个回文串的位置,不妨设它是奇数长度(偶数类似)。

那么问题变成了求一个i和d使得1<=d<=r(i)且pre[i-d]和suf[i+d]为真。

枚举i,实际上就是问pre[i-r(i)..i-1]和suf[i+1..i+r(i)]取反后 这两段有没有一个位置两者均为1,也就是and后不为0,暴力压位即可。

总时间复杂度为O(N2/32)O(N^2/32)O(N​2​​/32)。

*/

我的做法并没有用到压位(实际上是我不会),直接裸的manacher算法得出以 i 字符为中心的回文串半径p[i](这里的字符串是已经扩展过的,长度为0~len*2+1),然后直接枚举中心点 i 就好。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define maxn 20000
using namespace std;

char ss[maxn+20],s[maxn*2+20];
int p[maxn*2+20],id,mx,len;
bool pre[maxn*2+20],suf[maxn*2+20];

int main()
{
int i,j,k,t,len,c;
while(scanf("%d",&t)!=EOF)
for(i=1;i<=t;i++)
{
scanf("%s",ss),len=strlen(ss);
s[0]='*',s[1]='#';
for(j=0;j<len;j++)
s[2*j+2]=ss[j],s[2*j+3]='#';
k=2*len+1,mx=0,s[k+1]='%';
for(j=1;j<=k;j++)
{
if(mx>j)p[j]=min(p[2*id-j],mx-j);
else p[j]=1;
while(s[j-p[j]]==s[j+p[j]])p[j]++;
if(j+p[j]>mx)mx=j+p[j],id=j;
}

memset(pre,0,sizeof(pre));
memset(suf,0,sizeof(suf));

for(j=2;j<k;j++)
{
if(p[j]==j)pre[j+p[j]-1]=1;
if(j+p[j]==k+1)suf[j-p[j]+1]=1;
}

for(j=4;j<=k-3;j++)
{
for(c=islower(s[j])?1:2;c<=p[j];c+=2)
if(pre[j-c] && suf[j+c])break;
if(c<=p[j])break;
}

if(j>k-3)printf("No\n");
else printf("Yes\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: