[bzoj4477 Jsoi2015]字符串树 (可持久化trie)

传送门

Solution

复习下tire( ̄▽ ̄)/
裸的可持久化tire,我用树剖求了下LCA

Code

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define E(i,u) for(register int i=head[u],v;i;i=E[i].nxt)
using namespace std;

inline int read() {
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x*f;
} 

const int N=1e5+10;
int n,cnt,tot,q;
int head[N],fa[N],top[N],dep[N],rt[N],siz[N],son[N];
char ch[N][20];
struct Edge{int to,nxt;char *ch;}E[N<<1];
struct Node{int son[27],val;}nd[N<<4];

inline void add(int u,int v,char *s) {E[++cnt]=(Edge){v,head[u],s};head[u]=cnt;}

void ins(int o1,int &o2,int dep,char *s,int len) {
	nd[o2=++tot]=nd[o1];nd[o2].val++;if(dep>len) return ;
	ins(nd[o1].son[s[dep]-'a'],nd[o2].son[s[dep]-'a'],dep+1,s,len);
}

int qry(int o,char *s,int len) {
	F(i,1,len) o=nd[o].son[s[i]-'a'];
	return nd[o].val;
}

void dfs1(int u,int pre) {
	siz[u]=1;fa[u]=pre;dep[u]=dep[pre]+1;
	E(i,u) if((v=E[i].to)!=pre) {
		ins(rt[u],rt[v],1,E[i].ch,strlen(E[i].ch+1));
		dfs1(v,u); siz[u]+=siz[v];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
}

void dfs2(int u,int pre) {
	if(son[pre]==u) top[u]=top[pre]; else top[u]=u;
	if(son[u]) dfs2(son[u],u);
	E(i,u) if((v=E[i].to)!=pre&&v!=son[u]) dfs2(v,u);
}

int LCA(int x,int y) {
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	return dep[x]<dep[y]?x:y;
}

int main() {
	n=read();
	F(i,1,n-1) {
		int a=read(),b=read();scanf("%s",ch[i]+1);
		add(a,b,ch[i]);add(b,a,ch[i]);
	}
	dfs1(1,0);dfs2(1,0);
	q=read();
	while(q--) {
		int u=read(),v=read();scanf("%s",ch[0]+1);
		int len=strlen(ch[0]+1);
		int ans=qry(rt[u],ch[0],len)+qry(rt[v],ch[0],len)
			-2*qry(rt[LCA(u,v)],ch[0],len);
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2018-10-02 19:51  Menteur_hxy  阅读(232)  评论(0编辑  收藏  举报