zoukankan      html  css  js  c++  java
  • Shoi2011 双倍回文

    题目描述

    题解:

    建出PAM之后倍增跳查。

    貌似很裸。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 500050
    int n;
    char s[N];
    struct pnt
    {
        int pre,len,trs[27];
    }p[N];
    struct PAM
    {
        int las,tot;
        PAM()
        {
            las = tot = 1;
            p[0].pre=p[1].pre=1;
            p[1].len=-1;
        }
        bool mis(int i,int x)
        {
            return s[i]!=s[i-p[x].len-1];
        }
        void insert(int i)
        {
            int lp = las;
            while(mis(i,lp))lp=p[lp].pre;
            int c = s[i]-'a'+1;
            if(!p[lp].trs[c])
            {
                int np = ++tot;
                int tmp = p[lp].pre;
                while(mis(i,tmp))tmp = p[tmp].pre;
                p[np].pre = p[tmp].trs[c];
                p[np].len = p[lp].len+2;
                p[lp].trs[c] = np;
            }
            las = p[lp].trs[c];
        }
        int fa[N][21];
        void build()
        {
            for(int i=0;i<=tot;i++)fa[i][0]=p[i].pre;
            for(int i=1;i<=20;i++)
                for(int j=0;j<=tot;j++)
                    fa[j][i]=fa[fa[j][i-1]][i-1];
        }
        int ans;
        void bfs()
        {
            queue<int>q;
            q.push(0);
            while(!q.empty())
            {
                int u = q.front();
                q.pop();
                if(p[u].len%4==0)
                {
                    int tmp = u;
                    for(int i=20;i>=0;i--)
                        if(p[fa[tmp][i]].len*2>=p[u].len)tmp=fa[tmp][i];
                    if(p[tmp].len*2==p[u].len)
                        ans=max(ans,p[u].len);
                }
                for(int i=1;i<=26;i++)
                    if(p[u].trs[i])q.push(p[u].trs[i]);
            }
        }
        int cal()
        {
            ans=0;
            bfs();
            return ans;
        }
    }pam;
    int main()
    {
        scanf("%d%s",&n,s+1);
        for(int i=1;i<=n;i++)
            pam.insert(i);
        pam.build();
        printf("%d
    ",pam.cal());
        return 0;
    }
  • 相关阅读:
    PAT 1012 数字分类
    PAT 1046 划拳
    PAT 1021 个位数统计
    PAT 1003 我要通过!
    PAT 1031 查验身份证
    安装swoole
    PHP yield 分析,以及协程的实现,超详细版(上)
    PHP性能优化利器:生成器 yield理解
    swoole深入学习 8. 协程 转
    swoole| swoole 协程初体验 转
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10127179.html
Copyright © 2011-2022 走看看