[note]可持久化Trie

可持久化Trie

参考可持久化线段树的思想,修改的时候先直接复制,再对需要修改的点新建节点
可持久化Trie也是同样的做法,假设现在需要在原本Trie的基础上插入一个字符串
先把上个Trie的对应节点信息复制过来,对\(son[ch]\)新建节点

void insert(int x,int y,char*st){
	int l=strlen(st);
	for(int i=0;i<l;i++){
		int k=st[i]-'a';t[x].ch[k]=++tot;//新建
		x=t[x].ch[k];y=t[y].ch[k];
		t[x]=t[y];t[x].v++;//复制并更新
	}
}

查询先确定rt,然后类似Trie一样直接把字符串丢进去查即可

int query(int u,char*st){
	int l=strlen(st);
	for(int i=0;i<l;i++){
		int k=st[i]-'a';
		if(!t[u].ch[k])return 0;
		u=t[u].ch[k];
	}
	return t[u].v;
}

或者你二进制Trie是这么查的(下面是在一个区间中查异或max的模板)

int query(int x,int y,int num){
	int res=0;
	for(int i=24;i>=0;i--){
		int k=num>>i&1^1;
		if(t[y].ch[k]-t[x].ch[k]==0)k^=1;//没有能使该位为1的数
		else res|=(1<<i);
		x=t[x].ch[k];y=t[y].ch[k];
	}
	return res;
}

空间=Trie的空间*log
主要是一些字符串或者序列异或的题目中使用,注意到和主席树一样是可减的

常见套路

  • 路径问题就维护根到i的前缀Trie,然后把u,v,lca拿出来搞一搞
  • 子树问题求dfn,rk,直接按dfn跑一遍前缀Trie,之后当区间处理
posted @ 2018-11-07 17:12  sdzwyq  阅读(122)  评论(0编辑  收藏  举报