BZOJ4545 DQS的trie

14 篇文章 0 订阅
10 篇文章 0 订阅

造一个广义后缀自动机,LCT维护即可,询问1可以在插入的时候直接维护

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
struct vec{
	int to;
	int fro;
	int v;
};
struct LCT{
    int fa[MAXN],son[MAXN][2],sum[MAXN],ch[MAXN];
    int st[MAXN],tp;
    inline bool ir(int x){
        return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
    }
    inline void cot(int x,int y,int z){
        if(x){
            fa[x]=y;
        }
        if(y){
            son[y][z]=x;
        }
    }
	inline void rot(int x,bool z){
        int xx=fa[x],xxx=fa[xx];
        cot(son[x][z],xx,z^1);
        if(!ir(xx)){
            cot(x,xxx,son[xxx][1]==xx);
        }else{
            fa[x]=xxx;
        }
        cot(xx,x,z);
    }
    inline void toch(int x,int y){
        if(!x){
            return ;
        }
        sum[x]+=y;
        ch[x]+=y;
    }
    inline void pd(int x){
        toch(son[x][0],ch[x]);
        toch(son[x][1],ch[x]);
        ch[x]=0;
    }
    
    void splay(int x){
        st[++tp]=x;
        for(int i=x;!ir(i);i=fa[i]){
            st[++tp]=fa[i];
        }
        for(;tp;tp--){
            pd(st[tp]);
        }
        int xx=fa[x],xxx=fa[xx];
        while(!ir(x)){
            if(ir(xx)){
                rot(x,son[xx][0]==x);
            }else{
                bool z=son[xxx][0]==xx;
                if(son[xx][z]==x){
                    rot(x,z^1);
                    rot(x,z);
                }else{
                    rot(xx,z);
                    rot(x,z);
                }
            }
            xx=fa[x];
            xxx=fa[xx];
        }
    }
    void acs(int x){
        int t=0;
        while(x){
            splay(x);
            son[x][1]=t;
            t=x;
            x=fa[x];
        }
    }
    void cut(int x){
        acs(x);
        splay(x);
        fa[son[x][0]]=0;
        son[x][0]=0;
    }
    void link(int x,int y){
        cut(x);
        fa[x]=y;
    }
    int ask(int x){
        acs(x);
        splay(x);
        return sum[x];
    }
};
LCT T;
vec mp[MAXN*2];
int tai[MAXN],cnt;
int n,m;
char s[MAXN];
int mx[MAXN*2],fa[MAXN*2],son[MAXN*2][3];
int lst[MAXN],tot,rt;
bool vis[MAXN];
ll ans;
inline void be(int x,int y,int z){
	mp[++cnt].to=y;
	mp[cnt].fro=tai[x];
	tai[x]=cnt;
	mp[cnt].v=z;
}
inline void bde(int x,int y,int z){
	be(x,y,z);
	be(y,x,z);
}
int ins(int x,int lst){
    int p=lst,np=++tot;
    mx[np]=mx[p]+1;
    while(p&&(!son[p][x])){
        son[p][x]=np;
        p=fa[p];
    }
    if(!p){
        fa[np]=rt;
        T.link(np,rt);
        ans+=mx[np]-mx[fa[np]];
    }else{
        int q=son[p][x];
        if(mx[q]==mx[p]+1){
            fa[np]=q;
            T.link(np,q);
            ans+=mx[np]-mx[fa[np]];
        }else{
            int nq=++tot;
            mx[nq]=mx[p]+1;
            memcpy(son[nq],son[q],sizeof(son[q]));
            T.link(nq,fa[q]);
            fa[nq]=fa[q];
            ans+=mx[nq]-mx[fa[nq]];
			ans-=mx[q]-mx[fa[q]];
            T.link(q,nq);
            fa[q]=nq;
            ans+=mx[q]-mx[fa[q]];
            T.link(np,nq);
            fa[np]=nq;
			ans+=mx[np]-mx[fa[np]];
            T.acs(nq);
            T.splay(nq);
            T.sum[nq]=T.sum[q];
            while(p&&son[p][x]==q){
                son[p][x]=nq;
                p=fa[p];
            }
        }
    }
    T.acs(np);
    T.splay(np);
    T.toch(np,1);
    return np;
}
void dfs(int x){
	int i,y;
	vis[x]=1;
	for(i=tai[x];i;i=mp[i].fro){
		y=mp[i].to;
		if(!vis[y]){
			lst[y]=ins(mp[i].v,lst[x]);
			dfs(y);
		}
	}
}
char z[MAXN];
int main(){
	lst[1]=rt=tot=1;
	int i,o,x,y;
	scanf("%*d%d",&n);
	for(i=1;i<n;i++){
		scanf("%d%d%s",&x,&y,z);
		bde(x,y,z[0]-'a');
	}
	dfs(1);
	scanf("%d",&m);
	while(m--){
		scanf("%d",&o);
		if(o==1){
			printf("%lld\n",ans);
		}else if(o==2){
			scanf("%d%d",&o,&n);
			for(i=1;i<n;i++){
				scanf("%d%d%s",&x,&y,z);
				bde(x,y,z[0]-'a');
			}
			dfs(o);
		}else{
			scanf("%s",z+1);
			int p=rt;
			int len=strlen(z+1);
			bool flag=1;
			for(i=1;i<=len;i++){
				if(!son[p][z[i]-'a']){
					flag=0;
					break;
				}
				p=son[p][z[i]-'a'];
			}
			if(!flag){
				printf("0\n");
			}else{
				printf("%d\n",T.ask(p));
			}
		}
	}
	return 0;
}

/*
1
4
1 2 a 
1 3 b
2 4 b
6
1
2 2 4
2 5 b
2 6 c 
5 7 b
1
3 ab
2 6 3
6 8 a
6 9 b
1
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值