• BZOJ2342: [Shoi2011]双倍回文


    【传送门:BZOJ2342


    简要题意:

      给出一个字符串,求出一个最长的子串满足不但由两个回文子串组成,而且本身也是一个回文串,且这两个回文子串不重叠,并且这两个回文子串长度为偶数,也就是说原子串的长度一定是4的倍数


    题解:

      之前学了Manacher,看到这道题,A了之后,忘写博客,现在补一下

      先对原字符串搞一下Manacher,然后就for一遍,枚举构成双倍回文子串的中间点,然后再用一个for来向前找左端点,同时判断是否有相应的右端点与之对应


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int p[1100000];
    char s[510000],now[1100000];
    int n;
    int Manacher()
    {
        for (int i=1;i<=n;i++) now[2*i-1]='#',now[2*i]=s[i];
        n=n*2+1;
        now[n]='#';
        int pos=0,R=0;
        for(int i=1;i<=n;i++)
        {
            int j=2*pos-i;
            if(i<=R) p[i]=min(p[j],R-i);
            else p[i]=1;
            while(1<=i-p[i]&&i+p[i]<=n&&now[i-p[i]]==now[i+p[i]]) p[i]++;
            if(i+p[i]>R){pos=i;R=i+p[i];}
        }
    }
    int main()
    {
        scanf("%d",&n);
        scanf("%s",s+1);
        Manacher();
        int ans=0;
        for(int i=1;i<=n;i+=2) 
        {
            if(p[i]%2==0||ans>=p[i]-1) continue;
            for(int j=i-(p[i]-1)/2;j<i;j++)
            {
                if((i-j)*2<=ans) break;
                if((i-j)%2!=0) continue;
                if(j+p[j]-1>=i){ans=max(ans,(i-j)*2);break;}
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    第七章 下
    第七章 上
    第六章 下
    第六章 上
    第五章 下
    linux 系统通过安装包安装mysql 8 步骤(非MariaDB)
    热烈庆祝博客换了新皮肤
    异常处理
    栈计算逆波兰表达式
    栈计算中缀表达式
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7878686.html
Copyright © 2020-2023  润新知