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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值