字典树 / trie树

server/2025/1/11 18:47:48/

定义

当我手里有若干个字符串的时候,现在向你询问某个字符串时候是前面的这些字符串中的其中之一。如果我们用暴力的做法来求解的话,我可能需要对这些字符串进行逐一比对,效率是相当低的。那么这个时候我们就可以用 trie 树的结构简单高效的解决这个问题。

这个结构实现的原理有点像主席树(跑题了),字典树的根节点是一个空间点,没有任何含义,仅仅表示这棵字典树遍历的一个起点。

然后从根节点开始,构建我们的字典树,例如:把 “abcd”, “acd”, “bcd”, “abce” 这四个字符串构建成一棵字典树。那么这棵树就会长成下面的样子:
字典树1
我们从根节点出发,走到任意一个节点,走过的路径都是一个字符串。例如:空 -> a -> c -> d 就表示字符串 “acd”。

代码实现

首先先来说一下构建字典树的代码,根据个人的习惯和应用的环境,其实写法还是五花八门的,这里只是引出一种供大家参考。

int trie[maxn][30], tot = 1, cnt[maxn];
string s;void creat_trie(int id)
{int u = 1, len = s.size(); // u 表示当前在树上的位置for (int i = 0; i < len; i++) // 从前往后枚举每一个字符,这个被枚举出来的字符就是我们要在 u 下面添加的字符{int v = s[i] - 'a' + 1; // 用数字代替if (!trie[u][v]) // 如果还没被添加就添加trie[u][v] = ++tot; u = trie[u][v]; // 如果已经被添加了就顺着走}cnt[u]++; // 从根节点走到 u 表示的字符串是一个我们想要维护的字符串
}

首先我们让根节点的编号为 1,然后依次构建每一个字符串,也就是把一个字符串添加进字典树之后,再考虑下一个字符串。我们从根节点走到节点 u,路径上所有的点构成一个字符串(有可能是空串),那么在这个字符串后面如果再加上一个字符的话,我们假设这个字符是 ‘a’,那么我们就用一个节点来表示,如果这个点已经存在了,我们就不用管,直接移动到这个点就好,否则就新建一个点,给它一个编号,并让 trie[u][1] 等于这个新的点的编号,以此维护字典树的结构。

然后我们再来看如何查询一个字符串是否在这个字典树上。

int trie[maxn][30], tot = 1, cnt[maxn];
string s;bool check(string x)
{int u = 1;for (int i = 0; i < x.size(); i++){int a = x[i] - 'a' + 1;if (!trie[u][a]) // 看看下一个字符在不在树上return false;u = trie[u][a];}if (cnt[u])return true;return false;
}

那么这个代码就比较好理解了,也是从根节点出发,从前往后一个一个的找字符串中的字符,其中一个找不到就说明这个字符串不在字典树里面。如果找到最后,我们通过 cnt 发现这是一个我们想要维护的字符串,我们就返回真,否则就是假。

应用场景

算法比赛里面,trie 树的内容常常是搭配一些其他的内容进行的,经典的就是AC自动机,trie树 + kmp。
脱离算法比赛的话,IP地址路由、字符的搜索、字符频率的统计等等,常常与字典树有关。










本人能力有限,如果错误之处敬请指教!


http://www.ppmy.cn/server/157543.html

相关文章

数据结构-串

串的实现 在C语言中所使用的字符串就是串的数据类型的一种。 串的存储结构 定长顺序存储表示 类似于线性表的顺序存储结构&#xff0c;用一组连续的存储单元存储串值的字符序列。 #define MAXLEN 255 //预定义最大串长为255 ​ typedef struct SString {char ch[MAXLEN]; …

el-descriptions-item使用span占行不生效

需要实现的效果是客户状态单独占满一行 错误代码&#xff1a; <el-descriptions title"基本信息" :column"3"> <el-descriptions-item label"公司电话:">Suzhou</el-descriptions-item><el-descriptions-item label"…

【Rust自学】11.7. 按测试的名称运行测试

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.7.1. 按名称运行测试的子集 如果想要选择运行的测试&#xff0c;就将测试的名称&#x…

使用Python爬虫获取淘宝商品详情接口

以下是一篇关于使用Python获取淘宝商品详情接口的长篇文章&#xff1a; 淘宝商品详情接口简介 淘宝商品详情接口是淘宝开放平台提供的API之一&#xff0c;用于获取淘宝商品的详细信息。它可以帮助开发者获取商品的标题、价格、图片、库存、销量、评价等数据。这些数据对于电商…

理解Unity脚本编译过程:程序集

https://docs.unity3d.com/Manual/script-compilation.html 关于Unity C#脚本编译的细节&#xff0c;其中一个比较重要的知识点就是如何自定义Assembly。 预定义的assembly 默认情况下&#xff0c;Unity会按照这个规则进行编译。 PhaseAssembly nameScript files1Assembly-…

数组分割函数

这是一个数组分割函数&#xff0c;它的作用是将一个大数组按照指定的长度分割成多个小数组。 参数说明&#xff1a; array: 需要被分割的原始数组 subGroupLength: 每个小数组的长度 工作原理&#xff1a; splitArray(array, subGroupLength) {let index 0; …

二次雷达的详细介绍及代码示例

一、二次雷达的工作原理 二次雷达&#xff0c;又称空管雷达信标系统&#xff08;Air Traffic Control Radar Beacon System&#xff0c;ATCRBS&#xff09;&#xff0c;是一种无线电电子测位和辨认系统。它由地面询问雷达和飞机上的应答雷达&#xff08;又称雷达信标&#xff0…

Helm部署activemq

1.helm create activemq 创建helm文件目录 2.修改values.yaml 修改image和port 3. helm template activemq 渲染并输出 4. helm install activemq activemq/ -n chemical-park // 安装 5.启动成功