zoukankan      html  css  js  c++  java
  • 【单调队列DP+manacher】BZOJ2565-最长双回文串

    【题目大意】

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

    【思路】

    首先普通地求manacher,然后求出以每个位置为左端点和右端点的最长回文串长度l[i]和r[i]。

    l[i]=max{2*(j-i+1)-1}(j+p[j]-1>=i),r[i]同理。显然可以用单调队列维护一下。

    *网上好像大家没有用单调队列?我不清楚因为我只想出了单调队列的做法quq

    然后枚举一下。为了处理方便,我们只枚举'#'位置,这样能够保证除去该'#',左边字母和'#'数量相等,右边同理。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 const int MAXN=100000+50;
     8 char str[MAXN],s[MAXN*2+2];
     9 int len,p[MAXN],l[MAXN],r[MAXN];
    10 
    11 void init()
    12 {
    13     scanf("%s",str);
    14     s[0]='$',s[1]='#';
    15     len=strlen(str);
    16     for (int i=0,j=1;i<len;i++)
    17     {
    18         s[++j]=str[i];
    19         s[++j]='#';
    20     }
    21 }
    22 
    23 void solve()
    24 {
    25     int mx=0,mxid=0;
    26     for (int i=1;i<2*len+2;i++)
    27     {
    28         if (i<mx) p[i]=(p[2*mxid-i]<=(mx-i))?p[2*mxid-i]:(mx-i);
    29             else p[i]=1;
    30         while (s[i+p[i]]==s[i-p[i]]) p[i]++;
    31         if (i+p[i]-1>mx) mx=i+p[i]-1,mxid=i;
    32     }
    33 }
    34 
    35 void dp()
    36 {
    37     queue<int> que1;
    38     for (int i=1;i<2*len+2;i++)
    39     {
    40         while (!que1.empty() && que1.front()+p[que1.front()]-1<i) que1.pop();
    41         que1.push(i);
    42         l[i]=2*(i-que1.front()+1)-1;
    43     }
    44     
    45     queue<int> que2;
    46     for (int i=2*len+1;i>=1;i--)
    47     {
    48         while (!que2.empty() && que2.front()-p[que2.front()]+1>i) que2.pop();
    49         que2.push(i);
    50         r[i]=2*(que2.front()-i+1)-1;
    51     }
    52 }
    53 
    54 void printans()
    55 {
    56     int ans=-1;
    57     for (int i=1;i<2*len+2;i++) 
    58         if (s[i]=='#')
    59         {
    60             ans=max(ans,(l[i]-1)/2+(r[i]-1)/2);
    61         }
    62     printf("%d",ans);
    63 }
    64 
    65 int main()
    66 {
    67     init();
    68     solve();
    69     dp();
    70     printans();
    71     return 0;
    72 }
  • 相关阅读:
    jq封装的tab切换
    jquery高级函数
    jquery一些基本函数
    javascript中的事件冒泡和事件捕获
    prototype数组方法的实现
    瀑布流布局
    flex弹性布局
    js鼠标点击版tab切换
    js拖拽效果
    js根据className获取元素封装
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5751978.html
Copyright © 2011-2022 走看看