bzoj 2342 [Shoi2011]雙倍迴文(manacher,set)

 

【題目連接】php

 

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

 

【題意】spa

 

    求出形如w wR w wR的最長連續子串。code

 

【思路】blog

 

    用manacher算法計算出p[],表示以i與i+1爲中心的最長迴文字串長度/2排序

    枚舉第一個wR的結束位置x,當且僅當y-p[y]<=x且y<=x+p[x]/2子串[x+1,y]是一個答案,更新ans。get

    知足的條件是一個二維偏序,按照y-p[y]排序,在查詢x以前保證將全部知足第一個式子的x'加入set,查詢時找到x+p[x]/2在set中的前驅即爲最大的答案。string

 

【代碼】it

 

 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\n",ans);
50     return 0;
51 }

 

P.S. 新姿式[馬拉車]解鎖 :)io

相關文章
相關標籤/搜索