字典树
2022/3/30 6:22:20
本文主要是介绍字典树,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
字典树
树形结构, 消除冗余,实现结点的共用问题
本质上是一颗多叉树,$tr[u][i]$,表示当前结点的儿子。
数组模拟链表,邻接表表示的是边的信息。
e[idx], ne[idx] 存是的e[idx]这个结点到e[ne[idx]]这个结点的这条边的信息
字典树也同理
tr[p][u] 存的是他的下一个结点相当于ne[idx], 边的信息由二维数组tr的第二维来存储,idx相当于给下一个结点分配内存池,下一个结点还对应着一些边由tr[tr[p][u]][x]来存
插入操作
- 字符串
void insert(char str[]) { int p = 0; // 树形结构,从跟开始遍历 for (int i = 0; str[i]; i ++) { int u = str[i] - 'a'; if (!tr[p][u]) tr[p][u] = ++idx; // 没有这个子节点就创建一个,否则就直接走过去实现共用 p = tr[p][u]; } cnt[p] ++; // 表示当前这个点是某个有效信息 }
- 二进制数
void insert(int x) { int p = 0; for (int i = 30; i >= 0; i --) { int u = x >> i & 1; // 判断这一位是0,1 if (!tr[p][u]) tr[p][u] = ++idx; // 开点或共用 p = tr[p][u]; } num[p] ++; // 当前是一个数 }
查询操作
- 字符串出现次数
int query(char *str) { // 查询往下递归找即可 int p = 0; for (int i = 0; str[i]; i ++) { int u = str[i] - 'a'; if (!tr[p][u]) return 0; // 结点不存在,即字符串不存在 p = tr[p][u]; } return cnt[p]; }
- 最大异或对
int query(int x) { int p = 0, res = 0; for (int i = 30; i >= 0; i --) { int u = x >> i & 1; // 当前这一位是什么,贪心来看高位能不同就不同可以决定性 if (tr[p][!u]) res += 1 << i, p = tr[p][!u]; // 如果这一位可以取1那就直接取,否则就只能取零,因为只有两个结点 else p = tr[p][u]; // 所以每一个结点的两个子节点至少有一个是有的,因此不会走到空结点 // 往前缀相同的一些数的下面的位贪心 } return res; }
清空操作
我们相当于用$idx$来分配的内存池,所以直接
for (int i = 0; i <= idx; i ++) tr[i][j] = 0; idx = 0;
这篇关于字典树的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-01成为百万架构师的第一课:设计模式:Spring中的设计模式
- 2025-01-01一个基于注解驱动的可视化的DDD架构-超越COLA的设计
- 2025-01-01PlantUML 时序图 基本例子
- 2025-01-01plantuml 信号时序图
- 2025-01-01聊聊springboot项目如何优雅进行数据校验
- 2024-12-31自由职业者效率提升指南:3个时间管理技巧搞定多个项目
- 2024-12-31适用于咨询行业的项目管理工具:提升跨团队协作和工作效率的最佳选择
- 2024-12-31高效协作的未来:2024年实时文档工具深度解析
- 2024-12-31商务谈判者的利器!哪 6 款办公软件能提升春节合作成功率?
- 2024-12-31小团队如何选择最实用的项目管理工具?高效协作与任务追踪指南