Trie&可持久化Trie
WARNING:以下代码未经测试,若发现错误,欢迎指出qwq~
Trie树(字典树)
一种简单的数据结构,可存储大量字符串,可在$O(len)$的时间内完成插入,删除,查找等操作。
下面是一个简单的例子,对于abc,abd,abcd,bcd这四个字符串建Trie树,如下图:
其中,红色节点为一个字符串的结尾。对于任意节点,从根节点到该节点路径上字符组成的字符串即为该节点表示的字符串。
基本操作
相关变量
int root,cnt,ch[][],son[];
bool flag[];
void init(){
memset(flag,false,sizeof(flag));
memset(son,,sizeof(son));
memset(ch,,sizeof(ch));
root=cnt=;
return;
}
root即为根节点,cnt用于动态建树,ch[i][j]表示i节点的第j个子节点(表示字符char('a'+i))的编号,son[i]表示i节点的子节点数,flag[i]表示i节点是否为某个字符串的末尾。
插入
void ins(int rt,int dep){
if(dep==len){
flag[rt]=true;
return;
}
if(!ch[rt][s[dep]-'a']){
ch[rt][s[dep]-'a']=++cnt;
son[rt]++;
}
ins(ch[rt][s[dep]-'a'],dep+);
return;
}
删除
bool del(int rt,int dep){
if(dep==len){
if(flag[rt]){
flag[rt]=false;
return true;
}
return false;
}
if(!ch[rt][s[dep]-'a'])
return false;
if(del(ch[rt][s[dep]-'a'],dep+)){
if(!son[ch[rt][s[dep]-'a']]&&!flag[ch[rt][s[dep]-'a']]){
ch[rt][s[dep]-'a']=;
son[rt]--;
}
return true;
}
return false;
}
查找
bool query(int rt,int dep){
if(dep==len)
return flag[rt];
if(!ch[rt][s[dep]-'a'])
return false;
return query(ch[rt][s[dep]-'a'],dep+);
}
以上三个是Trie树的基本操作,下面来讲一下Trie树的其它运用。
拓展运用
求第k小字符串
存储以每个节点为根的子树中的末尾节点个数(size[i])即可。
void kth(int rt,int dep,int k){
if(k>size[rt]){
puts("have no kth string");
return;
}
for(int i=;i<;i++)
if(k>size[ch[rt][i]])
k-=size[ch[rt][i]];
else if(ch[rt][i]){
putchar('a'+i);
kth(ch[rt][i],dep+,k);
}
return;
}
最长公共前缀
用LCA求两个字符串对应的末尾节点的最近公共祖先即可,时间复杂度O(log2n)。
代码不贴了,懒~~~
最大异或值
将每个数转化为二进制,添加前缀0至相同位数,然后从最高位开始插入。查询时从最高位开始查询是否有与相应位置异或值为1的节点即可。
太水了,也不贴代码了~~~
可持久化Trie树
在做题过程中,我们常常会遇到求区间第k大字符串,区间与某数异或最大值之内的问题,我们便可以采用可持久化Trie树来解决这类问题。
依旧以abc,abd,abcd,bcd这四个字符串为例建可持久化Trie,如下图:
红色节点意义同上。
基本操作
相关变量
int cnt=,root[],size[],ch[][];
bool flag[];
void init(){
memset(flag,false,sizeof(flag));
memset(root,,sizeof(root));
memset(size,,sizeof(size));
memset(ch,,sizeof(ch));
cnt=;
return;
}
意义同上。
插入
void ins(int &now,int last,int dep){
if(!now)
now=++cnt;
if(dep==len){
flag[now]=true;
size[now]=size[last]+;
return;
}
int sign=s[dep]-'a';
for(int i=;i<;i++)
if(i!=sign){
ch[now][i]=ch[last][i];
size[now]+=size[ch[last][i]];
}
ins(ch[now][sign],ch[last][sign],dep+);
size[now]+=size[ch[now][sign]];
return;
}
区间第k小查询
void kth(int rl,int rr,int dep,int k){
if(k>size[rr]-size[rl]){
puts("have no kth string");
return;
}
for(int i=;i<;i++)
if(k>size[ch[rr][i]]-size[ch[rl][i]])
k-=size[ch[rr][i]]-size[ch[rl][i]];
else if(size[ch[rr][i]]-size[ch[rl][i]]>){
putchar('a'+i);
kth(ch[rl][i],ch[rr][i],dep+,k);
return;
}
return;
}
区间最大异或值
好吧,还是懒得打~~~
Trie&可持久化Trie的更多相关文章
- BZOJ.4212.神牛的养成计划(Trie 可持久化Trie)
BZOJ 为啥hzw的题也是权限题啊 考虑能够匹配\(s1\)这一前缀的串有哪些性质.对所有串排序,能发现可以匹配\(s1\)的是一段区间,可以建一棵\(Trie\)求出来,设为\([l,r]\). ...
- Luogu5283 十二省联考2019异或粽子(trie/可持久化trie+堆)
做前缀异或和,用堆维护一个五元组(x,l,r,p,v),x为区间右端点的值,l~r为区间左端点的范围,p为x在l~r中最大异或和的位置,v为该最大异或和,每次从堆中取出v最大的元素,以p为界将其切成两 ...
- 【BZOJ4137】火星商店问题(线段树分治,可持久化Trie)
[BZOJ4137]火星商店问题(线段树分治,可持久化Trie) 题面 洛谷 BZOJ权限题 题解 显然可以树套树,外层线段树,内层可持久化Trie来做. 所以我们需要更加优美的做法.--线段树分治. ...
- 可持久化Trie模板
如果你了解过 01 Trie 和 可持久化线段树(例如 : 主席树 ).那么就比较好去可持久化 Trie 可持久化 Trie 当 01 Trie 用的时候能很方便解决一些原本 01 Trie 不能解决 ...
- HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)
Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total Su ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
- 可持久化Trie & 可持久化平衡树 专题练习
[xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...
- HDU 4757 Tree(可持久化trie)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...
- 可持久化trie 学习总结
QAQ 以前一直觉得可持久化trie很难,今天强行写了一发觉得还是蛮简单的嘛 自己的模板是自己手写的,写了几道题目并没有出过错误 THUSC的第二题的解法五貌似就是可持久化trie,时间复杂度O(60 ...
随机推荐
- 动态网页爬取样例(WebCollector+selenium+phantomjs)
目标:动态网页爬取 说明:这里的动态网页指几种可能:1)须要用户交互,如常见的登录操作:2)网页通过JS / AJAX动态生成.如一个html里有<div id="test" ...
- 弯道超车,换一个思路,避免addEventListener为同一个元素重复赋予事件
addEventListener可以给同一个元素赋予多次同一个事件. 执行一次,就多一次事件效果.这不是我想要的. window.onload = function(){ var box = docu ...
- 【Linux】JDK+Eclipse 搭建C/C++开发环境
注:本文所提供的参考示例是在CentOS Linux环境下的安装,不保证适用于其他版本的Linux系统. · 安装前的注意事项 编译源代码是需要对应的代码编译工具的,本文中安装的Eclipse只 ...
- 如何保证对象线程内唯一:数据槽(CallContext)
CallContext 是类似于方法调用的线程本地存储区的专用集合对象,并提供对每个逻辑执行线程都唯一的数据槽.数据槽不在其他逻辑线程上的调用上下文之间共享.当 CallContext 沿执行代码路径 ...
- 安装、配置Vmware Esx Server 3.5视频全过程
Vmware Esx server 的特点是它无需任何操作系统就可在硬件上运行,它的内核是VMware自己开发的VMkernel,可以理解成为Windows系统内核NTOSKRNL.另外它完全依靠Li ...
- Bit、Byte、kb、KB、MB、KiB、MiB各表示什么意思?
1.Byte.bit:bit表示:位,是计算机中最小的数据单位.每一位的状态只能是0或1Byte表示:字节,8个二进制位构成1个字节,即1 Byte = 8 bit .1个英文字母或者数字占用1个字节 ...
- 学习参考《Python数据分析与挖掘实战(张良均等)》中文PDF+源代码
学习Python的主要语法后,想利用python进行数据分析,感觉<Python数据分析与挖掘实战>可以用来学习参考,理论联系实际,能够操作数据进行验证,基础理论的内容对于新手而言还是挺有 ...
- valgrind的说明使用和原理
编译 #gcc -g -o test test.c 内存检查#valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./test ...
- 多线程模式之Master-Worker
一. 介绍 需要使用Master-Worker的场景:主线程开了多个子进程(Worker进程)去执行任务时,主线程希望能收集到每个子进程的执行结果. 所以,Master-Worker模式基本上就是: ...
- c++中六种构造函数的实现以及9中情况下,构造函数的调用过程
六种构造函数的实现代码例如以下: #include<iostream> using namespace std; //c++中六种默认的构造函数 class Test { public: ...