hdu5340 Three Palindromes(manacher算法)

题目描述:

判断是否能将字符串S分成三段非空回文串。

解题思路:



源代码:

#include <cstdio>
#include <algorithm>
#define MAXN 20010
using namespace std;

int n;
char d[MAXN];///原始字符串
char st[MAXN*2];///经过manacher处理之后的字符串
int p[MAXN*2];///保存回文串半径,ps每个回文串长度一定为奇数

int ll[MAXN*2];///第一个回文串可能的所有半径
int rr[MAXN*2];///第三个回文串可能的所有半径

void manacher(){///manacher算法,可以去查询了解一下
    int i;
    st[0]='$';
    st[1]='#';
    for(i=1;d[i]!='\0';++i){
        st[i*2]=d[i];
        st[i*2+1]='#';
    }
    st[i*2]='\0';
    n=i*2-1;
    int MaxId=0,id;
    for(int i=1;i<=n;i++)
    {
        if(MaxId>i)
            p[i]=min(p[2*id-i],MaxId-i);
        else
            p[i]=1;
        while(st[i+p[i]]==st[i-p[i]])
            p[i]++;
        if(p[i]+i>MaxId){
            id=i;
            MaxId=p[i]+i;
        }
    }
}

int main(){
    int res;
    scanf("%d",&res);
    while(res--){
        scanf("%s",&d[1]);
        manacher();
        int l=0,r=0;
        for(int i=1;i<=n;i++){
            if(p[i]==i&&i!=1)///p[i]==i保证p[i]可以作为第一个回文串的半径,加入ll数组,i!=1保证第一个回文串不为空
                ll[l++]=p[i];
            if(p[i]+i-1==n&&i!=n)///与上面类似
                rr[r++]=p[i];
        }
        int i,j;
        for(i=l-1;i>=0;--i){
            for(j=0;j<=r-1;++j){///枚举第一个回文串和第三个回文串
                int tl=2*ll[i];///第二个字符串的开始位置
                int tr=n+1-2*rr[j];///第二个字符串的结束位置
                int tmp=(tl+tr)/2;///第二个字符串的中间位置,ps:这三个字符串都为奇数,可以自己想想
                if(tl>tr) continue;
                if(p[tmp]==1) continue;///第二个字符串为"#",也即是在原串中为空
                if(p[tmp]*2-1>=tr-tl+1)///以tmp为中点的回文串的长度大于等于第二个字符串的长度,符合题意跳出循环
                    break;
            }
            if(j<=r-1)
                break;
        }
        if(i>=0)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}






  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值