zoukankan      html  css  js  c++  java
  • BZOJ 2342: [Shoi2011]双倍回文 [Manacher + set]

    题意:

    求最长子串使得它有四个相同的回文串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();
    }
  • 相关阅读:
    亲和数
    改革春风吹满地
    处理选中图片
    项目架构(结构)搭建:主流结构(UITabBarController + 导航控制器)
    iOS应用启动main函数
    LaunchScreen&LaunchImage
    颜色常识
    折半查找法(二分法)
    冒泡排序
    多用户登录
  • 原文地址:https://www.cnblogs.com/candy99/p/6395906.html
Copyright © 2011-2022 走看看