• 双倍回文(bzoj 2342)


    Description

    Input

    输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

     

    Output

    输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0

    Sample Input

    16
    ggabaabaabaaball

    Sample Output

    12

    HINT

    N<=500000

    /*
        先跑一遍manacher,p[i]表示对称轴为i和i+1之间位置的最长回文串长度的一半,由于只求一种对称情况,所以不用加入无关字符。
        枚举x为对称轴,实际上对称轴在x到x+1之间,如果len(x+1,y)*4能更新最后的答案,需要满足y-p[y]<=x且y<=x+p[x]/2,按照y-p[y]排序一下,递推x的时候将符合1式的y插入set,在set中查找x+p[x]/2的前驱更新答案即可。
    */
    #include<iostream>
    #include<cstdio>
    #include<set>
    #include<algorithm>
    #define N 500010
    #define lon long long
    using namespace std;
    int n,p[N],q[N],ans;
    char ch[N];
    set<int> t;
    void manacher(){
        int mx=0,id;
        for(int i=1;i<=n;i++){
            if(mx>=i) p[i]=min(mx-i,p[id*2-i]);
            else p[i]=0;
            while(ch[i+p[i]+1]==ch[i-p[i]]) p[i]++;
            if(p[i]+i>mx) id=i,mx=p[i]+i;
        }
    }
    bool cmp(int a,int b){
        return a-p[a]<b-p[b];
    }
    int main(){
        scanf("%d%s",&n,ch+1);
        ch[0]='$';
        manacher();
        for(int i=1;i<=n;i++) q[i]=i;
        sort(q+1,q+n+1,cmp);
        int now=1;
        for(int i=1;i<=n;i++){
            while(now<=n&&q[now]-p[q[now]]<=i){
                t.insert(q[now]);
                now++;
            }
            set<int>::iterator tmp=t.upper_bound(i+p[i]/2);
            if(tmp!=t.begin()){
                ans=max(ans,(*--tmp-i)*4);
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    人月神话阅读笔记01
    HTML中常用meta整理
    前端开发中的SEO
    webGL学习笔记
    webGL 学习教程
    HTMl5的sessionStorage和localStorage
    Validform使用
    gulp详细入门教程
    gulp.spriteSmith使用
    gulp.spritesmith修改px为rem单位
  • 原文地址:https://www.cnblogs.com/harden/p/6675756.html
Copyright © 2020-2023  润新知