Hdu 5340 Three Palindromes 最大回文串 Manacher

24 篇文章 0 订阅
22 篇文章 0 订阅

Three Palindromes

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 80    Accepted Submission(s): 21


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
 题意,是给出一个字符串,能否分成三个非空回文串。
我们可以发现 第一个和第三个串,一定是最大回文串的某个串,Manacher 求出最大回文串的长度,枚举第一个和最后一个,中间直接判断,中点的最大回文串是否包括了就可以了。复杂度为o(n * n).
具体manacher算法参见  Manacher算法
#define N 110050
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int T,n,a,pri[N],ans,len,sn = 0,top[N],tail[N],pn,ln;
bool dp[N][4];
pii seg[N];
bool Manacher(char str[],int len){
    char tstr[N+N];
    int p[N + N],l2 =0,mi;
    tstr[l2++] = '#';
    for(int i =0;i<len;i++){
        tstr[l2++] = str[i];
        tstr[l2++] = '#';
    }
    p[0] = 0;mi = 0;
    for(int i = 1;i<l2;i++){
        int mi2 = mi + mi - i;
        if(mi + p[mi] >= i) p[i] = min(mi2 - (mi - p[mi]),p[mi2]);
        else p[i] = 0;
        if(p[i] == 0 ||  mi2 - p[mi2] == mi - p[mi]){
            int maxx = p[i]+1;
            while(i- maxx >= 0 && i+maxx < l2 && tstr[i-maxx] == tstr[i+maxx]){
                maxx++;
            }
            p[i] = maxx - 1;
        }
        if(p[i] + i > p[mi] + mi) mi = i;
    }
    int ans = -1;sn = 0;pn = ln = 0;
    for(int i = 1;i < l2 - 1;i++){
        if(i - p[i] == 0) top[pn++]  = i;
        if(i + p[i] == l2 - 1) tail[ln++] = i;
    }
    for(int i = 0;i < pn;i++){
        for(int j = ln - 1;j>=0;j--){
            int s1 = top[i] + p[top[i]] + 1,s2 = tail[j] - p[tail[j]] - 1;
            if(s1 > s2 )
            break;
            int mid = (s1 + s2)/2;
            if(p[mid] >= mid - s1) return true;
        }
    }
    return false;
    //printf("%d\n",ans);
}
char str[N];
int main()
{
    while(S(T)!=EOF)
    {
        while(T--){
            SS(str);
            len = strlen(str);
            if(Manacher(str,len))
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}


Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5342  5341  5339  5338  5337 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值