zoukankan      html  css  js  c++  java
  • BZOJ 2342: [Shoi2011]双倍回文 马拉车算法/并查集

    2342: [Shoi2011]双倍回文

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1123  Solved: 408

    题目连接

    http://www.lydsy.com/JudgeOnline/problem.php?id=2342

    Description

    输入分为两行,第一行为一个整数n,表示字符串的长度,第二行有n个连续的小写的英文字符,表示字符串的内容。

    Input

    输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

    Output

    输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。

    Sample Input

    16
    ggabaabaabaaball

    Sample Output

    12

    HINT

    题解:

    用传说中的马拉车算法,算出所有的回文中心,以及P数组,然后我们就枚举i-(i-p[i])/2位置到第i位置的p[j]是否大于i

    然后如果大于就说明这是一个双倍回文

    但是,这样子会T,那么我们肿么优化呢?

    那就献祭出并查集吧~!

    ♪(^∇^*),100ms就跑过去啦

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 500005
    #define mod 10007
    #define eps 1e-9
    const int inf=0x7fffffff;   //无限大
    /*
    
    */
    //**************************************************************************************
    char s[maxn];
    char str[maxn*2];
    int p[maxn*2];
    int fa[maxn*2];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int l;
    int manacher(char s[],int l)
    {
       int i,j,k,ans=0;
       for(i=1;i<=l;++i)str[i<<1]=s[i],str[(i<<1)+1]='#';
       str[1]='#';str[l*2+1]='#';str[0]='&';str[l*2+2]='$';
       l=l*2+1;j=0;
       for(i=1;i<=l;)
       {
           while(str[i-j-1]==str[i+j+1])++j;
           p[i]=j;if(j>ans)ans=j;
           for(k=1;k<=j&&p[i]-k!=p[i-k];++k)p[i+k]=min(p[i-k],p[i]-k);
           i+=k;j=max(j-k,0);
       }
       return ans;
    }
    int get(int p)
    {
        if(fa[p]==p)
            return p;
        fa[p]=get(fa[p]);
        return fa[p];
    }
    int main()
    {
        l=read();
        scanf("%s",s+1);
        manacher(s,l);
        l=l*2+1;
        for(int i=1;i<=l;i++)
        {
            if(str[i]=='#')
                fa[i]=i;
            else
                fa[i]=i+1;
        }
        int j;
        int ans=0;
        for(int i=3;i<l;i+=2)
        {
            j=get(max(i-p[i]/2,1));
            for(;j<i&&j+p[j]<i;fa[j]=get(j+1),j=fa[j]);
            if(j<i)
                if((i-j)*2>ans)
                ans=(i-j)*2;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    P2048 [NOI2010]超级钢琴
    [LOJ#6468.] 魔法
    [牛客小白月赛18] Forsaken的数列
    [JSOI2011]柠檬
    [TJOI2015]组合数学
    【单调队列优化】[CF372C] Watching Fireworks is Fun
    【线段树】[Luogu P4198]楼房修建
    Python资源
    人生的几个阶段
    两种解读,生活的意义和方法
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4364050.html
Copyright © 2011-2022 走看看