• bzoj 2565 manacher


    Description

            顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。

      输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。


     

    Input

            一行由小写英文字母组成的字符串S。


    Output

            一行一个整数,表示最长双回文子串的长度。


     

    Sample Input

    baacaabbacabb

    Sample Output

    12
     

    Data Constraint

     
     

    Hint

    【样例说明】


    从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。

     

    【数据范围】

        对于10%的数据,2≤|S|≤103。

      对于30%的数据,2≤|S|≤104。

      对于100%的数据,2≤|S|≤105。

    思路:

    先做一遍MANACHER,然后枚举分界点(为#)

    那么以这个点为分界的最长双回文串会由最左边的能覆盖到这个点的串和最右边的能覆盖到这个点的串组成

    那么扫两遍求出每个点最左和最右能覆盖到它的回文串中心。(就是反过来求以每个点为中心的回文串能覆盖哪些点

    然后枚举即可

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    
    char s[200011];
    int r[200011],lm[200011],rm[200011];
    int i,n,x,z,q,len,j;
    char c;
    
    void Read()
    {
        while(c=getchar(),c<'a'||c>'z');
        s[++n]='#';
        s[++n]=c;
        while(c=getchar(),c>='a'&&c<='z'){
            s[++n]='#';
            s[++n]=c;
        }
        s[++n]='#';
    }
    
    void Manacher()
    {
        int i,len,l,k;
        len=0;
        for(i=1;i<=n;i++){
            if(len<i){
                l=0;
                while(s[i-l]==s[i+l]&&i-l>=1&&i+l<=n)l++;
                r[i]=l;
            }
            else{
                l=min(len-i+1,r[k+k-i]);
                while(s[i+l]==s[i-l]&&i-l>=1&&i+l<=n)l++;
                r[i]=l;
            }
            if(i+r[i]-1>len){
                len=i+r[i]-1;
                k=i;
            }
        }
    }
    
    int main()
    {
        Read();
        Manacher();
        r[0]=0;
        len=0;
        for(i=1;i<=n;i++){
            if(i+r[i]-1>len){
                for(j=len+1;j<=i+r[i]-1;j++)lm[j]=i;
                len=i+r[i]-1;
            }
            if(len==n)break;
        }
        len=n+1;
        for(i=n;i>=1;i--){
            if(i-r[i]+1<len){
                for(j=i-r[i]+1;j<=len-1;j++)rm[j]=i;
                len=i-r[i]+1;
            }
            if(len==1)break;
        }
        for(i=1;i<=n;i++)if(s[i]=='#'){
            z=(rm[i]-i+1)*2-1+(i-lm[i]+1)*2-1-1;
            if(z/2>q)q=z/2;
        }
        printf("%d
    ",q);
    }
  • 相关阅读:
    python unittest--TestSuit类--通过unittest.TestSuite()类直接构建,或者通过TestSuite实例的addTests、addTest方法构建
    Cannot read property 'toLowerCase' of undefined
    Vue 中登录功能的简单实现
    git 常用命令
    js 锚点定位的简单方法
    Vue element-ui 使用Loading服务按需引入的坑
    防抖 节流
    element-ui 日期选择器-开始结束日期选择限制
    vue elment-ui 对navTab导航组件封装
    vue 监听窗口变化对页面部分元素重新渲染
  • 原文地址:https://www.cnblogs.com/applejxt/p/3813454.html
Copyright © 2020-2023  润新知