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的更多相关文章

  1. BZOJ.4212.神牛的养成计划(Trie 可持久化Trie)

    BZOJ 为啥hzw的题也是权限题啊 考虑能够匹配\(s1\)这一前缀的串有哪些性质.对所有串排序,能发现可以匹配\(s1\)的是一段区间,可以建一棵\(Trie\)求出来,设为\([l,r]\). ...

  2. Luogu5283 十二省联考2019异或粽子(trie/可持久化trie+堆)

    做前缀异或和,用堆维护一个五元组(x,l,r,p,v),x为区间右端点的值,l~r为区间左端点的范围,p为x在l~r中最大异或和的位置,v为该最大异或和,每次从堆中取出v最大的元素,以p为界将其切成两 ...

  3. 【BZOJ4137】火星商店问题(线段树分治,可持久化Trie)

    [BZOJ4137]火星商店问题(线段树分治,可持久化Trie) 题面 洛谷 BZOJ权限题 题解 显然可以树套树,外层线段树,内层可持久化Trie来做. 所以我们需要更加优美的做法.--线段树分治. ...

  4. 可持久化Trie模板

    如果你了解过 01 Trie 和 可持久化线段树(例如 : 主席树 ).那么就比较好去可持久化 Trie 可持久化 Trie 当 01 Trie 用的时候能很方便解决一些原本 01 Trie 不能解决 ...

  5. HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)

    Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Su ...

  6. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

  7. 可持久化Trie & 可持久化平衡树 专题练习

    [xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...

  8. HDU 4757 Tree(可持久化trie)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...

  9. 可持久化trie 学习总结

    QAQ 以前一直觉得可持久化trie很难,今天强行写了一发觉得还是蛮简单的嘛 自己的模板是自己手写的,写了几道题目并没有出过错误 THUSC的第二题的解法五貌似就是可持久化trie,时间复杂度O(60 ...

随机推荐

  1. 每天一个linux命令(九月)

    2014-09-02 top 实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器 命令參数: -b 批处理 -c 显示完整的治命令 -I 忽略失效过程 -s 保密模式 -S 累积模 ...

  2. Android 4.3 系统裁剪——删除不使用的app及添加自己app

    删除不使用的apk 系统自带的app位置是在/android4.3/packages/apps 以下是一些APP作用分析: | |– BasicSmsReceiver | |– Bluetooth ( ...

  3. Python(六) Python 函数

    一.认识函数 help(方法名字)  help(round) 1.功能性 2.隐藏细节 3.避免编写重复的代码 4.组织代码 自定义函数 二.函数的定义及运行特点 # 递归 def sum_num(n ...

  4. SqlCommand的四大方法

    SqlCommand类的方法 ---->>>1.ExecuteNonQuery(); 它的返回值类型为int型.多用于执行增加,删除,修改数据,返回受影响的行数.当select操作时 ...

  5. Innodb锁的类型

    Innodb锁的类型 行锁(record lock) 行锁总是对索引上锁,如果某个表没有定义索引,mysql就会使用默认创建的聚集索引,行锁有S锁和X锁两种类型. 共享锁和排它锁 Innodb锁有两种 ...

  6. eclipse 安装javaEE插件 和html\xml\jsp编辑器

    1 在Eclipse中菜单help选项中选择install new software选项 2 在work with 栏中输入 http://download.eclipse.org/releases/ ...

  7. localtime死锁——多线程下fork子进程

    近期測试我们自己改进的redis,发如今做rdb时,子进程会一直hang住.gdb attach上.堆栈例如以下: (gdb) bt #0 0x0000003f6d4f805e in __lll_lo ...

  8. JavaScript数组的某些操作(二)

    7.颠倒数组中元素的顺序(注意:不是为数组排序)--reverse方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...

  9. hdu 5375 - Gray code(dp) 解题报告

    Gray code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  10. OpenCASCADE Face Normals

    OpenCASCADE Face Normals eryar@163.com Abstract. 要显示一个逼真的三维模型,其顶点坐标.顶点法向.纹理坐标这三个信息必不可少.本文主要介绍如何在Open ...