• Bzoj2342 [Shoi2011]双倍回文


    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1915  Solved: 713
    [Submit][Status][Discuss]

    Description

     

    Input

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

     

    Output

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

    Sample Input

    16
    ggabaabaabaaball

    Sample Output

    12

    HINT

    N<=500000

    http://hzwer.com/5375.html

    算法太神以至于看不懂,先存下代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<set>
     7 using namespace std;
     8 const int mxn=800010;
     9 int p[mxn],q[mxn];
    10 int len,ans;
    11 char s[mxn];
    12 set<int>t;
    13 int cmp(int a,int b){
    14     return (a-p[a])<(b-p[b]);
    15 }
    16 void manacher(){
    17     int id=0,mx=0;
    18     for(int i=1;i<=len;i++){
    19         if(mx>=i)p[i]=min(p[id]+id-i,p[2*id-i]);
    20         else p[i]=0;
    21         while(s[i+1+p[i]]==s[i-p[i]])p[i]++;
    22         //字符串长度是偶数,对称轴在i和i+1之间,
    23         //那么左边是i-p[i],右边对称位置是i+1+p[i] 
    24         if(p[i]+i>mx)mx=p[i]+i,id=i;
    25     }
    26     return;
    27 }
    28 int main(){
    29     scanf("%d %s",&len,s+1);
    30     s[0]='$';
    31     int i,j;
    32     manacher();
    33     for(i=1;i<=len;i++)q[i]=i;
    34     sort(q+1,q+len+1,cmp);
    35     int now=1;
    36     for(i=1;i<=len;i++){
    37         while(now<=len && q[now]-p[q[now]]<=i){
    38             t.insert(q[now]);
    39             now++;
    40         }
    41         set<int>::iterator tmp=t.upper_bound(i+p[i]/2);
    42         if(tmp!=t.begin())ans=max(ans,(*--tmp-i)*4);
    43     }
    44     printf("%d
    ",ans);
    45     return 0;
    46 }
  • 相关阅读:
    1.Go环境安装
    IDEA启动Tomcat控制台中文显示乱码
    专注的含义
    翻出一封古老的信
    若有所思
    B+Tree与B-Tree 的区别
    Redis集群 什么是slots
    夜深人静,听雨
    随心所想
    本性可以改吗
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5678203.html
Copyright © 2020-2023  润新知