zoukankan      html  css  js  c++  java
  • 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);
    }
  • 相关阅读:
    HDFS文件系统简单的Java读写操作
    HDFS文件读写流程简单图解
    大数据入门---------------------Java部分开始
    Hive 基础入门
    安卓 2.3 安装及环境搭建
    字节流与字符流的区别详解(转)
    Java File 类的使用方法详解(转)
    ThinkPHP Session 使用
    PHP TP框架
    对象和数组的相互转化
  • 原文地址:https://www.cnblogs.com/applejxt/p/3813454.html
Copyright © 2011-2022 走看看