• bzoj 2342 [Shoi2011]双倍回文(manacher,set)


    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2342

    【题意】

        求出形如w wR w wR的最长连续子串。

    【思路】

        用manacher算法计算出p[],表示以i与i+1为中心的最长回文字串长度/2

        枚举第一个wR的结束位置x,当且仅当y-p[y]<=x且y<=x+p[x]/2子串[x+1,y]是一个答案,更新ans。

        满足的条件是一个二维偏序,按照y-p[y]排序,在查询x之前保证将所有满足第一个式子的x'加入set,查询时找到x+p[x]/2在set中的前驱即为最大的答案。

    【代码】

     1 #include<set>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int N = 5e5+10;
     8 
     9 set<int> t;
    10 set<int> ::iterator it;
    11 
    12 char s[N];
    13 int n,ans,p[N],q[N];
    14 
    15 bool cmp(int a,int b)
    16 {
    17     return (a-p[a])<(b-p[b]);
    18 }
    19 
    20 void manacher()
    21 {
    22     int mx=0,id;
    23     for(int i=1;i<=n;i++)
    24     {
    25         if(mx>=i)p[i]=min(mx-i,p[2*id-i]);
    26         else 
    27             p[i]=0;
    28         while(s[i+p[i]+1]==s[i-p[i]]) p[i]++;
    29         if(p[i]+i>mx)id=i,mx=p[i]+i;
    30     }
    31 }
    32 
    33 int main()
    34 {
    35     scanf("%d%s",&n,s+1);
    36     s[0]='#';
    37     manacher();
    38     for(int i=1;i<=n;i++) q[i]=i;
    39     sort(q+1,q+n+1,cmp);
    40     int now=1;
    41     for(int i=1;i<=n;i++)
    42     {
    43         while(now<=n&&q[now]-p[q[now]]<=i)
    44             t.insert(q[now++]);
    45         it=t.upper_bound(i+p[i]/2);
    46         if(it!=t.begin())
    47             ans=max(ans,(*--it-i)*4);
    48     }
    49     printf("%d
    ",ans);
    50     return 0;
    51 }

    P.S. 新姿势[马拉车]解锁 :)

  • 相关阅读:
    MySQL日志
    MySQL索引和事务
    【收集】腾讯AlloyTeam
    js基础知识点(只有点)
    【扩展】Canvas绘制列表的尝试
    开播 开博 凯博
    【总结】移动web问题小结
    〖前端开发〗HTML/CSS基础知识学习笔记
    第四次读书笔记——《代码大全》(续)
    C++笔记(1)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5348634.html
Copyright © 2020-2023  润新知