Trie树

Trie(字典树)是一种用于实现字符串检索的多叉树。

Trie的每一个节点都可以通过 c 转移到下一层的一个节点。

我们可以看作可以通过某个字符转移到下一个字符串状态,直到转移到最终态为止。这是后话……

我们以插入了字符串 abaab 三个字符串的Trie树为例:

其实一看图就非常清晰了

在上图中,如果我们需要继续插入一个字符串 abc,那么就只需要新建一个节点即可

思路清晰,那么代码如何实现?

  • 首先是插入部分:
struct Node {
int kids[65];
int cnt;
} nodes[N]; #define kids(p, j) nodes[p].kids[j]
#define cnt(p) nodes[p].cnt void insert(char * s, int len) {
int p = 0;
for (int i = 0; i < len; ++i) {
int j = discrete(s[i]);
if (!kids(p, j)) kids(p, j) = ++usage; // 新建节点
p = kids(p, j);
}
    ++cnt(p);
}

discrete指的是离散化,例如这里是将 a-z0-25 表示

最终的 cnt 表示有几个字符串在当前节点结束。

  • 然后是查询部分

我们还是利用类似的思路,一个一个向下走。

例如我们要查询字符串 aba,那么我们从根节点 0 开始,通过 a 走到 1 节点,通过 b 走到 4 节点,发现没有 a 的子节点,表明没有这个字串,结束寻找。

// 这里是查询这个字符串出现了多少次,为0就是没有出现
int count(char * s, int len) {
int p = 0;
for (int i = 0; i < len; ++i) {
int j = discrete(s[i]);
if (!kids(p, j)) return 0;
p = kids(p, j);
}
return cnt(p);
}

其实主要操作就这两个,我们考虑一下空间和时间复杂度:

时间复杂度很明显是与字符串长度相关的,我们每处理一个字符走一个节点,也就是 \(O(L)\) 的复杂度,那么总的复杂度就是 \(O(NL)\)

至于空间复杂度,每处理一个字符串至多新建 \(L\) 个节点,那么就是 \(O(L)\) ,每一个节点的大小关乎字符串的字符集大小,所以我们认为是 \(O(C)\) 那么总共就是 \(O(NLC)\) ,但是,在实际中,远远达不到此复杂度(除非毒瘤出题人想卡你),例如最初的图,一共 4 个字符串,但是只有 5 个节点……

例题

【模板】字典树 - 洛谷

注意题意,以询问所给作为前缀,求有多少个字符串满足此前缀

那么我们需要魔改一下 insert 函数即可……将 ++cnt(p) 放入循环中即可

还请读者仔细思考

[USACO12DEC]First! G - 洛谷

这道题非常的神奇……考虑先建Trie树,如果某一个字符串的字典序比其他任何字符串都大,那么一定不存在为其前缀的字符串。

再考虑字典序,如果使 s 其字典序最大,那么每一个分叉点上,s[i] 比其他所有存在的分叉都要大。

如样例:omm, moo, mom

如果要使 omm 最大那么在第一层上满足 o > m,其他层上没有分叉。

如果要使 moo 最大,那么第一层上满足 m > o,第三层上满足 o > m,条件相悖,所以不可行。

其他同理。

那么我们如何判断条件相悖?可以借鉴 2-SAT 的思路,通过大于关系建图,如果存在环,那么不可行。

判环用拓扑,谁用Tarjan啊

最终,每一个串判断一遍即可。

[BJOI2016]IP地址 - 洛谷

这道题就是Trie的一种特殊用法。

有点类似线段树的区间标记。

我们考虑改变一个规则对其整个子树都有影响,那么我们考虑什么时候影响抵消?更深的点会阻挡了标记的下传。那么我们记录一下各个点的标记情况,通过类似线段树的方法下传标记即可。

正确性显然。

扩展

Trie树实际上是 AC自动机 和 回文自动机 等自动机的载体,需要经过一点点小变换。

在此不展开叙述,详见我的其他文章。

算法学习笔记(15): Trie(字典树)的更多相关文章

  1. 道长的算法笔记:Trie字典树

    Trie模板 Trie 是一种用于实现字典序快速检索的多叉树结构,Trie 每个节点都有若干的字符指针,若在扫扫描字符串时扫到字符 \(c\),则沿着当前节点 \(c\) 字符指针走向该指针指向的节点 ...

  2. 算法学习笔记(20): AC自动机

    AC自动机 前置知识: 字典树:可以参考我的另一篇文章 算法学习笔记(15): Trie(字典树) KMP:可以参考 KMP - Ricky2007,但是不理解KMP算法并不会对这个算法的理解产生影响 ...

  3. 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  4. 算法导论:Trie字典树

    1. 概述 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. Trie一词来自retrieve,发音为/tr ...

  5. 标准Trie字典树学习二:Java实现方式之一

    特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! 系列文章: 1. 标准Trie字典树学习一:原理解析 2.标准T ...

  6. SQL反模式学习笔记3 单纯的树

    2014-10-11 在树形结构中,实例被称为节点.每个节点都有多个子节点与一个父节点. 最上层的节点叫做根(root)节点,它没有父节点. 最底层的没有子节点的节点叫做叶(leaf). 中间的节点简 ...

  7. SQL反模式学习笔记15 分组

    目标:查询得到每组的max(或者min等其他聚合函数)值,并且得到这个行的其他字段 反模式:引用非分组列 单值规则:跟在Select之后的选择列表中的每一列,对于每个分组来说都必须返回且仅返回一直值. ...

  8. C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  9. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

  10. 算法学习笔记(5): 最近公共祖先(LCA)

    最近公共祖先(LCA) 目录 最近公共祖先(LCA) 定义 求法 方法一:树上倍增 朴素算法 复杂度分析 方法二:dfs序与ST表 初始化与查询 复杂度分析 方法三:树链剖分 DFS序 性质 重链 重 ...

随机推荐

  1. 在游戏运营行业,Serverless 如何解决数据采集分析痛点?

    简介: 众所周知,游戏行业在当今的互联网行业中算是一棵常青树.在疫情之前的 2019 年,中国游戏市场营收规模约 2884.8 亿元,同比增长 17.1%.2020 年因为疫情,游戏行业更是突飞猛进. ...

  2. 汽车之家:基于 Flink + Iceberg 的湖仓一体架构实践

    简介: 由汽车之家实时计算平台负责人邸星星在 4 月 17 日上海站 Meetup 分享的,基于 Flink + Iceberg 的湖仓一体架构实践. 内容简要: 一.数据仓库架构升级的背景 二.基于 ...

  3. 如何评估Serverless服务能力,这份报告给出了40条标准

    简介: 如今,已经有评测机构给出了40条标准来对Serverless的服务能力进行评估,这些评估细则既是技术生态繁荣发展的一种表现,也可以作为新进入者评估Serverless落地成效的一种参考依据. ...

  4. Paillier半同态加密:原理、高效实现方法和应用

    ​简介: <数据安全法>已于9月1日起正式实施,两个月后<个人信息保护法>也将开始施行,意味着数据安全和隐私保护方面的监管将会在年内陆续到位.在合规收紧大背景下,"数 ...

  5. 解密万亿参数M6模型预训练背后的分布式框架Whale

    ​简介: 最近,阿里云PAI团队和达摩院智能计算实验室一起发布"低碳版"巨模型M6,大幅降低万亿参数超大模型训练能耗.借助我们自研的Whale框架仅使用480卡GPU,即训练出了规 ...

  6. VSCode 打开ESP32工程问题

    一.无法跳转 问题现象: 打开ESP32工程头文件提示波浪线不跳转,如下图所示: 解决办法: 删除工程中.vsccode文件夹下的所有文件 VSCode 中打开命令行搜索 ESP-IDF 找到`添加 ...

  7. C语言程序设计-笔记5-数据类型和表达式

    C语言程序设计-笔记5-数据类型和表达式 例6-1  大小写英文字母转换.输入一样字符,将其中的大写字母转换为相应的小写字母后输出,小写字母转换为相应的大写字母后输出,其他字符按原样输出. #incl ...

  8. 【python爬虫案例】用python爬豆瓣音乐TOP250排行榜!

    目录 一.爬虫对象-豆瓣音乐TOP250 二.python爬虫代码讲解 三.同步视频 四.获取完整源码 一.爬虫对象-豆瓣音乐TOP250 今天我们分享一期python爬虫案例讲解.爬取对象是,豆瓣音 ...

  9. ansible系列(33)--ansible实战之部署WEB集群架构(3)

    目录 1. 应用环境部署 1.1 nginx编译部署 1.2 PHP编译部署 1.3 mariadb二级制部署 1.4 redis部署 1.5 NFS部署 1.6 keepalived+LVS部署 1 ...

  10. IDEA连接github

    在IDEA中添加github账号: File-->Settings-->Version Control-->GitHub 点击 + 号,添加账号可以选择账号密码登陆或者使用token ...