Apio2014 回文串

Posted LiGuanlin1124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apio2014 回文串相关的知识,希望对你有一定的参考价值。

题目描述

题解:

这篇题解是关于manacher+SAM的。

因为我还不会回文自动机我会学的

SAM支持给出一个串,求出现次数。

manacher支持找回文串。

然后放在一起,当每个节点回文半径扩展时查询。

这样时间是O(n^2)的。

为了时间,我们可以O(nlogn)预处理每个节点沿pre指针条2^k次到哪个点。

然后查询O(nlogn)。

貌似只有bz卡空间?

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 300050
#define ll long long
char s0[N],s1[2*N];
int len,n;
struct node{int pre,len,trs[26];}p[2*N];
int siz[2*N],rt[N];
struct SAM
{
    int tot,las;
    SAM(){tot=las=1;}
    int insert(int c)
    {
        int np,nq,lp,lq;
        np=++tot;
        siz[np]=1;
        p[np].len = p[las].len+1;
        for(lp=las;lp&&!p[lp].trs[c];lp=p[lp].pre)
            p[lp].trs[c]=np;
        if(!lp)p[np].pre = 1;
        else
        {
            lq = p[lp].trs[c];
            if(p[lq].len==p[lp].len+1)p[np].pre = lq;
            else
            {
                nq=++tot;
                p[nq]=p[lq];
                p[nq].len = p[lp].len+1;
                p[lq].pre = p[np].pre = nq;
                while(p[lp].trs[c]==lq)
                {
                    p[lp].trs[c]=nq;
                    lp=p[lp].pre;
                }
            }
        }
        return las = np;
    }
    int hs[2*N],topo[2*N],fa[2*N][21];
    int i,j,x;
    void build()
    {
        for(i=1;i<=tot;i++)hs[p[i].len]++;
        for(i=1;i<=tot;i++)hs[i]+=hs[i-1];
        for(i=1;i<=tot;i++)topo[hs[p[i].len]--]=i;
        for(i=tot;i>=1;i--)
        {
            x = topo[i];
            siz[p[x].pre]+=siz[x];
            fa[x][0]=p[x].pre;
        }
        for(i=1;i<=tot;i++)
        {
            x = topo[i];
            for(j=1;j<=20;j++)
                fa[x][j]=fa[fa[x][j-1]][j-1];
        }
    }
    int len;
    int query()
    {
        x = rt[x];
        for(i=20;i>=0;i--)
        {
            if(p[fa[x][i]].len>=len)
            {
                x=fa[x][i];
            }
        }
        return x;
    }
}sam;
void init()
{
    s1[0]=!;
    s1[++n]=#;
    for(int i=1;i<=len;i++)
    {
        s1[++n]=s0[i];
        s1[++n]=#;
    }
    s1[n+1]=@;
}
int rp[2*N];
ll manacher()
{
    init();
    ll ans = 0;
    int mid = 0,mx = 0,i,u;
    for(i=1;i<=n;i++)
    {
        if(i<=mx)rp[i]=min(rp[2*mid-i],mx-i+1);
        else
        {
            rp[i]=1;
            if(i%2==0)ans=max(ans,1ll*siz[p[1].trs[s1[i]-a]]);
        }
        while(s1[i-rp[i]]==s1[i+rp[i]])
        {
            rp[i]++;
            if((i-rp[i]+1)%2==0)
            {
                sam.x = (i+rp[i]-1)/2,sam.len = rp[i];
                u = sam.query();
                ans = max(ans,1ll*siz[u]*rp[i]);
            }
        }
        if(i+rp[i]-1>mx)mx=i+rp[i]-1,mid=i;
    }
    return ans;
}
int main()
{
    scanf("%s",s0+1);
    len = strlen(s0+1);
    for(int i=1;i<=len;i++)
        rt[i]=sam.insert(s0[i]-a);
    sam.build();
    printf("%lld
",manacher());
    return 0;
}

 

以上是关于Apio2014 回文串的主要内容,如果未能解决你的问题,请参考以下文章

P3649 [APIO2014]回文串(回文自动机)

[BZOJ3676][APIO2014]回文串(Manacher+SAM)

bzoj3676: [Apio2014]回文串 回文树

P3649 [APIO2014]回文串

「APIO2014」回文串 (二分+hash)

P3649 [APIO2014]回文串