hdu5340 Three Palindromes(manacher算法)

来源:互联网 发布:网络心理学的杂志 编辑:程序博客网 时间:2024/05/16 08:18

题目描述:

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

解题思路:



源代码:

#include <cstdio>#include <algorithm>#define MAXN 20010using 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;}






1 0
原创粉丝点击