BZOJ 2342 Manacher

思路:
首先用manacher可以求出以i和i+1中间为对称轴,最长回文串能扩增的长度p[i]。

然后4*(y-x)能更新答案,当且仅当y≤x+p[x]/2且y-p[y]≤x。

按i-p[i]将所有点排序,依次插入set中,查询x+p[x]/2的前驱更新答案,时间复杂度O(n*logn)。

——AaronPolaris

//By SiriusRen
#include <set>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 555555
set<int>st;
int l,ans,p[N],mx,id,tp;char s[N];
struct Node{int x,y;}node[N];
bool cmp(Node a,Node b){return a.x<b.x;}
int main(){
    scanf("%d%s",&l,s+1),s[0]='%'; 
    for(int i=1;i<=l;i++){
        if(mx>i)p[i]=min(p[id*2-i],mx-i);
        else p[i]=0;
        while(s[i+p[i]+1]==s[i-p[i]])p[i]++;
        if(i+p[i]>mx)mx=i+p[i],id=i;
    }
    for(int i=1;i<=l;i++){
        node[i].x=i-p[i],node[i].y=i;
    }sort(node+1,node+1+l,cmp);
    for(int i=1;i<=l;i++){
        while(tp<l&&node[tp+1].x<=i)st.insert(node[++tp].y);
        ans=max(ans,(*--st.lower_bound(i+p[i]/2+1)-i)*4);
    }printf("%d
",ans);
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532127.html