HDU

Sample Input
6
1 a
1 b
2 a
2 c
3
4
8
1 a
2 a
2 a
1 a
3
1 b
3
4
Sample Output
4
5
4
5
11

题意:多组输入,开始字符串为空,支持4中操作: 1,在字符串首加字符; 2,在字符串尾加字符; 3,查询字符串不同本质的回文串个数; 4,查询回文串个数总和

思路:因为支持首尾加入,所以和常规的回文树有些不同。 参考了YYB的博客。 发现首尾互相影响,当且仅当整个字符串是回文串。 其他情况两头正常加即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=100010;
struct PAT
{
    struct node{
        int len,num,fail,son[26];
    }t[maxn];
    int n,tot,s[maxn<<1],L,R,suf,pre; ll ans;
    void init()
    {
        memset(t,0,sizeof(t));
        memset(s,-1,sizeof(s));
        tot=1; L=100000; R=L-1;
        suf=pre=0; ans=0;
        t[1].len=-1; t[0].fail=t[1].fail=1;
    }
    void add(int c,int n,int &last,int op){
        int p=last; s[n]=c;
        while(s[n]!=s[n-op-op*t[p].len]) p=t[p].fail;
        if(!t[p].son[c]){
            int v=++tot,k=t[p].fail;
            while(s[n]!=s[n-op*t[k].len-op]) k=t[k].fail;
            t[v].fail=t[k].son[c];
            t[v].len=t[p].len+2;
            t[v].num=t[t[v].fail].num+1;
            t[p].son[c]=v;
        }
        last=t[p].son[c]; ans+=t[last].num;
        if(t[last].len==R-L+1) suf=pre=last;
    }
}T;
int main()
{
    int N;
    while(~scanf("%d",&N)){
        T.init(); int opt;
        rep(i,1,N){
            scanf("%d",&opt); char s[3];
            if(opt==1){
                scanf("%s",s);
                T.add(s[0]-'a',--T.L,T.pre,-1);
            }
            else if(opt==2){
                scanf("%s",s);
                T.add(s[0]-'a',++T.R,T.suf,1);
            }
            else if(opt==3)
                printf("%d
",T.tot-1);
            else printf("%lld
",T.ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/10355974.html