BZOJ 2342 [Shoi2011]双倍回文(manacher+堆+set)

题意

N<=500000

题解

维护一个set可以用堆来解决。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<set>
 7 #include<queue>
 8 using namespace std;
 9 const int N=500100;
10 int str[N*2],m,p[N*2];
11 int n,f[N],now,ans;
12 char s[N];
13 struct hhh{
14     int l,r;
15     bool operator <(const hhh &a)const{
16         return a.r<r;
17     }
18 }c[N];
19 set<int> se;
20 priority_queue<hhh> q;
21 void init(){
22     str[0]=str[1]='#';
23     for(int i=1;i<=n;i++){
24         str[i*2]=s[i];
25         str[i*2+1]='#';
26     }
27     m=n*2+1;
28 }
29 void manacher(){
30     int mx=0,id;
31     for(int i=1;i<=m;i++){
32         if(mx>i)p[i]=min(p[id-(i-id)],id+p[id]-i);
33         else p[i]=1;
34         while(str[i-p[i]]==str[i+p[i]])p[i]++;
35         if(i+p[i]-1>mx)mx=i+p[i]-1,id=i;
36     }
37 }
38 int main(){
39     scanf("%d",&n);
40     scanf("%s",s+1);
41     init();
42     manacher();
43     for(int i=1;i<=n;i++){
44         f[i]=p[i*2+1]/2;
45         c[i].l=i;
46         c[i].r=i+f[i];
47     }
48     for(int i=1;i<=n;i++){
49         if(i-1+f[i-1]>=i){
50             se.insert(i-1);
51             q.push(c[i-1]);
52         }
53         while(!q.empty()&&q.top().r<i){
54             se.erase(q.top().l);
55             q.pop();
56         }
57         set<int>::iterator it=se.lower_bound(i-f[i]/2);
58         if(it!=se.end()){
59             ans=max(ans,(i-*it)*4);
60         }
61     }
62     printf("%d",ans);
63     return 0;
64 }
原文地址:https://www.cnblogs.com/Xu-daxia/p/9555168.html