BZOJ 4545: DQS的trie

来源:互联网 发布:地理空间数据云ftp 编辑:程序博客网 时间:2024/06/06 03:17

一道后缀自动机的好题,综合了后缀自动机一些重要的操作。
对于询问一,我们边建树边维护。
对于询问三,我们用一个LCT来维护。
(记得开long longQAQ)

#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<cstring>#include<string>#include<iostream>#include<iomanip>#include<algorithm>using namespace std;struct splay{    splay *fa,*ls,*rs;    int add_mark,val;    splay(int);    void push_down();    void add(int v);}*null=new splay(0);splay :: splay(int _=0){    fa=ls=rs=null;    add_mark=0;    val=_;}void splay :: add(int v){    val+=v;    add_mark+=v;}void splay :: push_down(){    if(add_mark)    {        if(ls!=null) ls->add(add_mark);        if(rs!=null) rs->add(add_mark);        add_mark=0;    }}void right(splay *x){    splay *y=x->fa;    y->ls=x->rs;    x->rs->fa=y;    x->fa=y->fa;    x->rs=y;    if(y==y->fa->ls) y->fa->ls=x;    else if(y==y->fa->rs) y->fa->rs=x;    y->fa=x;}void left(splay *x){    splay *y=x->fa;    y->rs=x->ls;    x->ls->fa=y;    x->fa=y->fa;    x->ls=y;    if(y==y->fa->ls) y->fa->ls=x;    else if(y==y->fa->rs) y->fa->rs=x;    y->fa=x;}void push_down(splay *x){    if(x==x->fa->ls || x==x->fa->rs) push_down(x->fa);    x->push_down();}void splaying(splay *x){    push_down(x);    while(1)    {        splay *y=x->fa;        splay *z=y->fa;        if(x!=y->ls && x!=y->rs) break;        if(y!=z->ls && y!=z->rs)        {            if(x==y->ls) right(x);            else left(x);            break;        }        if(x==y->ls)        {            if(y==z->ls) right(y);            right(x);        }        else if(x==y->rs)        {            if(y==z->rs) left(y);            left(x);        }    }}void access(splay *x){    splay *y=null;    while(x!=null)    {        splaying(x);        x->rs=y;        y=x;        x=x->fa;    }}void cut(splay *x){    access(x);    splaying(x);    x->ls->fa=null;    x->ls=null;}void link(splay *x,splay *y){    cut(x);    x->fa=y;}struct sam{    sam *parent,*son[26];    int max_len;    splay *tree;    sam(int _=0):parent(0x0),max_len(_)    {        memset(son,0,sizeof(son));        tree=new splay(0);    }}*root=new sam,*mempool[1000000];long long ans=0;sam* my_insert(sam *p,int x){    /*if(p->son[x] && p->son[x]->max_len==p->max_len+1)    {        p->son[x]->tree->val++;        return p->son[x];    }*/    sam *np=new sam(p->max_len+1);    while(p && !p->son[x])    {        p->son[x]=np;        p=p->parent;    }    if(!p)    {        np->parent=root;        link(np->tree,root->tree);    }    else    {        sam *q=p->son[x];        if(p->max_len==q->max_len-1)        {            np->parent=q;            link(np->tree,q->tree);        }        else        {            sam *nq=new sam(p->max_len+1);            nq->parent=q->parent;            ans-=q->max_len-q->parent->max_len;            link(nq->tree,q->parent->tree);            memcpy(nq->son,q->son,sizeof(nq->son));            q->parent=nq;np->parent=nq;            ans+=q->max_len-q->parent->max_len;            ans+=nq->max_len-nq->parent->max_len;            link(q->tree,nq->tree);            link(np->tree,nq->tree);            push_down(q->tree);            nq->tree->val=q->tree->val;            while(p && p->son[x]==q)            {                p->son[x]=nq;                p=p->parent;            }        }    }    ans+=np->max_len-np->parent->max_len;    access(np->tree);    splaying(np->tree);    np->tree->add(1);    return np;}char s[1000000];struct bian{    int l,r,v;}a[1000000];int tot=0;int fir[1000000];int firc[1000000];int nex[1000000];int nexc[1000000];void add_edge(int l,int r,char c,int cloc){    a[++tot].l=l;    a[tot].r=r;    a[tot].v=c;    if(firc[l]!=cloc)    {        firc[l]=cloc;        fir[l]=0;    }    if(nexc[tot]!=cloc)    {        nex[tot]=0;        nexc[tot]=cloc;    }    nex[tot]=fir[l];    fir[l]=tot;}void dfs(int u,int from,int v){    if(from!=0) mempool[u]=my_insert(mempool[from],v-'a');    for(int o=fir[u];o!=0;o=nex[o])    {        //cout<<a[o].r<<" ";        if(a[o].r!=from) dfs(a[o].r,u,a[o].v);    }}int search_ans(){    sam *o=mempool[1];    for(int i=0;s[i];i++)    {        if(!o->son[s[i]-'a']) return 0;        o=o->son[s[i]-'a'];    }    push_down(o->tree);    return o->tree->val;}int main(){    int id;    scanf("%d",&id);    int n;    scanf("%d",&n);    for(int i=1;i<n;i++)    {        int l,r;        char c[5];        scanf("%d%d%s",&l,&r,c);        add_edge(l,r,c[0],0);        add_edge(r,l,c[0],0);    }    mempool[1]=root;    dfs(1,0,0);    int m;    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        int opt;        scanf("%d",&opt);        if(opt==1) printf("%lld\n",ans);        if(opt==2)        {            int rt,si;            scanf("%d%d",&rt,&si);            tot=0;            for(int j=1;j<si;j++)            {                int l,r;                char c[5];                scanf("%d%d%s",&l,&r,c);                add_edge(l,r,c[0],i);                add_edge(r,l,c[0],i);            }            dfs(rt,0,0);        }        if(opt==3)        {            scanf("%s",s);            printf("%d\n",search_ans());        }    }    return 0;}
0 1