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. 【VBA研究】用VBA取得EXCEL随意列有效行数

    作者:iamlaosong 用VBA对Excel文件进行处理的时候,keyword段的列号编程时往往是不知道的.须要通过參数设定才干知道,因此.我们编程的时候,就不能用这种语句取有效行数: linen ...

  2. Lesson 1 Basic Concepts: Part 1

    www.how-to-build-websites.com/basic-concepts/part1.php An introduction to domain names, web servers, ...

  3. vSphere5安装配置视频教程

    vSphere5安装配置视频教程 本文出自 "李晨光原创技术博客" 博客,请务必保留此出处http://chenguang.blog.51cto.com/350944/819550

  4. Android 勤用RXJava compose操作符消除重复代码

    相信小伙伴在使用RXJava与Retrofit请求网络时,都有遇到过这样的场景,在IO线程请求网络解析数据,接着返回主线程setData.更新View试图,那么也肯定熟悉下面这几句代码: .subsc ...

  5. Pycharm在Ubuntu14.04中的基本使用指南

    前几天给大家分享了:如何在VMware虚拟机中安装Ubuntu14.04系统.今天给大家分享一下在Ubuntu14.04中如何简单的使用Pycharm.1.启动Pycharm,将进入Pycharm的启 ...

  6. React开发实时聊天招聘工具 -第一章

    第一章 课程道学 6个页面 弱化css Antd-mobile作为组件库 Redux 状态管理 React-Router 路由 Axios异步请求 后端Express框架 Socket.io 数据库: ...

  7. pythong中的全局变量的调用和嵌套函数中变量的使用

    全局变量调用:想要在自定义的函数中使用全局变量,就得要在函数用关键字global声明,然后就可以对全局变量进行修改.嵌套函数中的变量的调用:要在嵌套的变量中,使用nonlocal的声明'''num = ...

  8. 初尝Perl -- 使用aapt给apk软件包批量重命名

    不知道什么是Perl猛戳这个链接 http://zh.wikipedia.org/wiki/Perl     任务:                 随着手机/平板的各方面性能的不断发展(CPU,内存 ...

  9. 【Henu ACM Round#17 C】Kitahara Haruki's Gift

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 判断sum/2这个价值能不能得到就可以了. 则就是一个01背包模型了. 判断某个价值能否得到. f[j]表示价值j能否得到. f[0 ...

  10. vim 基础学习之普通模式

    .操作 = 操作符 + 动作 aaa bbb例如,d是删除命令,b是移动到距离光标最近的字符串开头当我们执行db的时候,就会删除光标(不包括光标位置)到最近字串开头之间的字符dj则会删除光标所在行以及 ...