hdu5421 Victor and String【回文树】

题目大意:

开始时给一个空字符串,要求支持在首尾加字符,询问本质不同的回文串个数和所有回文串个数。

解题思路:

很容易想到修改一下回文树的写法,从中间向两边拓展节点,本质不同的回文串个数就是回文树节点个数,而每加一个字母,增加的回文串个数就是num[last]。
注意到我们用了两个指针last[0],last[1]维护最长回文前(后)缀,所以在首(尾)添加字符后如果整个串变成了回文串,last[0]、last[1]都会变化为同一个节点。

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int N=200005;
int n;
struct PAM
{
    int tot,last[2],l[2],s[N],len[N],num[N],fail[N],son[N][26];
    inline int newnode(int l)
    {
        len[++tot]=l;
        return tot;
    }
    inline void clear()
    {
        memset(son,0,sizeof(son));
        memset(fail,0,sizeof(fail));
        memset(num,0,sizeof(num));
        memset(len,0,sizeof(len));
        tot=-1,last[0]=last[1]=0,l[1]=n,l[0]=n+1;
        newnode(0),newnode(-1),fail[0]=1,fail[1]=0;
    }
    inline int get_fail(int x,int t)
    {
        s[l[0]-1]=s[l[1]+1]=-1;
        while(s[l[t]]!=s[l[t]+(t?-1:1)*(len[x]+1)])
            x=fail[x];
        return x;
    }
    inline int add(int c,int t)
    {
        s[l[t]+=(t?1:-1)]=c;
        int cur=get_fail(last[t],t);
        if(!son[cur][c])
        {
            int now=newnode(len[cur]+2);
            fail[now]=son[get_fail(fail[cur],t)][c];
            son[cur][c]=now;
        }
        last[t]=son[cur][c],num[last[t]]=num[fail[last[t]]]+1;
        if(l[1]-l[0]+1==len[last[t]])last[t^1]=last[t];
        return num[last[t]];
    }
}pam;
int main()
{
    //freopen("lx.in","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        pam.clear();
        int op;ll ans=0;char s[2];
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&op);
            if(op==1)scanf("%s",s),ans+=pam.add(s[0]-'a',0);
            else if(op==2)scanf("%s",s),ans+=pam.add(s[0]-'a',1);
            else if(op==3)printf("%d\n",pam.tot-1);
            else printf("%lld\n",ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值