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;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10127179.html