首页 > 其他 > 详细

BZOJ 2342: [Shoi2011]双倍回文 [Manacher + set]

时间:2017-02-14 01:04:17      阅读:231      评论:0      收藏:0      [点我收藏+]

题意:

求最长子串使得它有四个相同的回文串SSSS相连组成


 

枚举中间x

找右边的中间y满足 y-r[y]<=x y<=x+r[x]/2

用个set维护

注意中间只能是#

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N=1e6+5;
typedef long long ll;
int n;
char s[N],str[N];
int r[N];
void Manacher(char s[],int n){
    int p=0,a;
    for(int i=1;i<=n;i++){
        r[i]=i<p?min(p-i+1,r[2*a-i]):1;
        while(s[i-r[i]]==s[i+r[i]]) r[i]++;
        if(i+r[i]-1>p) p=i+r[i]-1,a=i;
    }
}
void iniStr(char str[],char s[]){
    for(int i=1;i<=n;i++)
        s[(i<<1)-1]=#,s[i<<1]=str[i];
    s[n<<1|1]=#;
    s[0]=@;s[(n<<1)+2]=$;
}
set<int> Set;
set<int>::iterator it;
struct data{
    int v,id;
    bool operator <(const data a)const{return v<a.v;}
}a[N];
int ans;
void solve(){
    n=n<<1|1; int p=0;
    for(int i=1;i<=n;i++) if(i&1) a[++p].v=i-r[i],a[p].id=i;
    sort(a+1,a+1+p);
    int now=1;
    for(int i=1;i<=n;i++) if(i&1){
        while(now<p&&a[now].v<=i) Set.insert(a[now].id),now++;
        it=--Set.upper_bound(i+r[i]/2);
        if(it!=Set.begin()) ans=max(ans,(*it)-i);
    }
    printf("%d",ans*2);
}
int main(){
    freopen("in","r",stdin);
    scanf("%d%s",&n,str+1);
    iniStr(str,s);
    Manacher(s,n<<1|1);
    solve();
}

 

BZOJ 2342: [Shoi2011]双倍回文 [Manacher + set]

原文:http://www.cnblogs.com/candy99/p/6395906.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!