• hdoj5340(Manacher+枚举)


    题目链接:https://vjudge.net/problem/HDU-5340

    题意:给定一个长度为n的字符串,问能不能将其分解成3个回文串。(n<=2e4)

    思路:

      先用Manacher算法得到以每个点为中心的最大回文串的左右边界le[i]、ri[i]。并且当le[i]==1(即该回文串向左可以到达字符串的边界)时,记录下来,le1[ri[i]]=1,表示存在一个回文串左边界为1,右边界为ri[i]。同理,当ri[i]==n-1(字符串右边界)时,ri1[le[i]]=1。

      然后遍历中间的回文串的回文中心,令t1=p[i]-1(回文串长度),t2=le[i](回文串左边界),t3=ri[i](回文串右边界),当le1[t2]==1&&ri1[t3]==1时即找到了方案。如果不满足,t1-=2,t2+=2,t3-=2,继续判断,直到t1<=0。要注意的是当t2==1或者t3==n-1时该回文串不能作为中间回文串。

      详见代码。

    AC code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int maxn=2e4+5;
    int T,n,ans,p[maxn<<1],le[maxn<<1],ri[maxn<<1];
    int le1[maxn<<1],ri1[maxn<<1];
    char s[maxn<<1],ss[maxn];
    
    void manacher(){
        int mid=0,r=0;
        for(int i=1;i<n;++i){
            if(r>=i) p[i]=min(p[(mid<<1)-i],r-i+1);
            while(s[i-p[i]]==s[i+p[i]]) ++p[i];
            if(i+p[i]>r) r=i+p[i]-1,mid=i;
            int tmp=p[i]-1;
            le[i]=i-tmp,ri[i]=i+tmp;
            if(le[i]==1) le1[ri[i]]=1;
            if(ri[i]==n-1) ri1[le[i]]=1;
        }
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%s",ss);
            ans=0;
            n=strlen(ss);
            s[0]='~',s[1]='|';
            for(int i=0;i<n;++i)
                s[2*i+2]=ss[i],s[2*i+3]='|';
            n=2*n+2;
            for(int i=0;i<n;++i)
                p[i]=0,le1[i]=0,ri1[i]=0;
            manacher();
            for(int i=1;i<n;++i){
                int t1=p[i]-1,t2=le[i],t3=ri[i];
                if(t2==1||t3==n-1){
                    t1-=2;
                    t2+=2;
                    t3-=2;
                }
                while(t1>0){
                    if(le1[t2]&&ri1[t3]){
                        ans=1;
                        break;
                    }
                    t1-=2;
                    t2+=2;
                    t3-=2;
                }
                if(ans) break;
            }
            if(ans) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    函数
    特殊集合
    集合
    数组复习
    数组
    IPython--转
    python 单例模式总结
    拼多多笔试题
    python 创建实例--待完善
    转--算法时间复杂度
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/12418993.html
Copyright © 2020-2023  润新知