HDU-5421Victor and String

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5421

因为要在前面插字符,所以维护一个前缀链和后缀链,在同一棵回文树上搞,如果有某个最长回文后缀(或前缀)的长度为总长,那让前缀(或后缀)的last也赋为当前结点。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define ll long long
#define maxn 200500
using namespace std;
int n,op;
char c;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
struct data{
    ll sum;
    int L,R,tot,fail[maxn],l[maxn],nxt[maxn][30],s[maxn],last[2],cnt[maxn];
    int newnode(int len){
        clr(nxt[tot],0);
        l[tot]=len; cnt[tot]=0;
        return tot++;
    }
    void init(){
        tot=0; sum=0;
        newnode(0); newnode(-1);
        fail[0]=1;
        last[0]=last[1]=1;
        clr(s,-1);
        L=n; R=n-1;
    }
    int getfail(int op,int v){
        if (op) while (s[R-l[v]-1]!=s[R]) v=fail[v];
        else while (s[L+l[v]+1]!=s[L]) v=fail[v];
        return v;
    }
    void add(int op,int c){
        if (op) s[++R]=c; else s[--L]=c;
        int cur=getfail(op,last[op]);
        if (!nxt[cur][c]){
            int now=newnode(l[cur]+2);
            fail[now]=nxt[getfail(op,fail[cur])][c];
            nxt[cur][c]=now;
            cnt[now]=cnt[fail[now]]+1;
        } last[op]=nxt[cur][c];
        if (l[last[op]]==R-L+1) last[op^1]=last[op];
        sum+=cnt[last[op]];
    }
}T;
int main(){
 //   freopen("in.txt","r",stdin);
    while (~scanf("%d",&n)){
        T.init();
        rep(i,1,n){
            op=read(); 
            if (op<=2) {
                c=getchar();
                T.add(op-1,c-'a');
            }
            else if(op==3) printf("%d\n",T.tot-2);
            else printf("%lld\n",T.sum);
        }
    }
    return 0;
}

 

posted on 2015-11-24 13:58  ctlchild  阅读(211)  评论(0编辑  收藏  举报

导航