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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]排序,使用set维护符合条件的y。

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

 

【代码】

 

 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 }

 

以上是关于bzoj 2342 [Shoi2011]双倍回文(manacher,set)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2342 [Shoi2011]双倍回文 (manacher)

bzoj2342 [Shoi2011]双倍回文

BZOJ 2342: SHOI2011 双倍回文

bzoj 2342: [Shoi2011]双倍回文

[BZOJ2342][SHOI2011]双倍回文

BZOJ 2342: [Shoi2011]双倍回文