字典树(Trie树)的实现及应用
>>字典树的概念
Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。
与二叉查找树不同,Trie树的键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

Trie树优点是最大限度地减少无谓的字符串比较,查询效率比较高。核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
(1) 插入、查找的时间复杂度均为O(N),其中N为字符串长度。
(2) 空间复杂度是26^n级别的,非常庞大(可采用双数组实现改善)。
它有3个基本性质:
根节点不包含字符,除根节点外每一个节点都只包含一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符都不相同。
>>Trie树和DFA,确定有限状态自动机
trie树实际上是一个DFA,通常用转移矩阵表示。行表示状态,列表示输入字符,(行,列)位置表示转移状态。这种方式的查询效率很高,但由于稀疏的现象严重,空间利用效率很低。也可以采用压缩的存储方式即链表来表示状态转移,但由于要线性查询,会造成效率低下。
>>Trie树的实现
Trie树的创建要考虑的是父节点如何保存孩子节点,主要有链表和数组两种方式:
(1)使用节点数组,因为是英文字符,可以用Node[26]来保存孩子节点(如果是数字我们可以用Node[10]),这种方式最快,但是并不是所有节点都会有很多孩子,所以这种方式浪费的空间太多
(2)用一个链表根据需要动态添加节点。这样我们就可以省下不小的空间,但是缺点是搜索的时候需要遍历这个链表,增加了时间复杂度。
给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie:

可以看出:
每条边对应一个字母。
每个节点对应一项前缀。叶节点对应最长前缀,即单词本身。
单词inn与单词int有共同的前缀“in”, 因此他们共享左边的一条分支,root->i->in。同理,ate, age, adv, 和ant共享前缀"a",所以他们共享从根节点到节点"a"的边。
(1)查询操作
查询操作非常简单。比如要查找int,顺着路径i -> in -> int就找到了。
(2)如何构建
Trie树的构建也很简单,无非是逐一把每则单词的每个字母插入Trie。
插入前先看前缀是否存在。如果存在,就共享,否则创建对应的节点和边。
比如要插入单词add,就有下面几步:
考察前缀"a",发现边a已经存在。于是顺着边a走到节点a。
考察剩下的字符串"dd"的前缀"d",发现从节点a出发,已经有边d存在。于是顺着边d走到节点ad
考察最后一个字符"d",这下从节点ad出发没有边d了,于是创建节点ad的子节点add,并把边ad->add标记为d。
>>Java实现Trie树
使用数组实现Trie树。
>>字典树应用场景
(1) 字符串检索
事先将已知的一些字符串(字典)的有关信息保存到trie树里,查找另外一些未知字符串是否出现过或者出现频率。
举例:
给出N 个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。
给出一个词典,其中的单词为不良单词。单词均为小写字母。再给出一段文本,文本的每一行也由小写字母构成。判断文本中是否含有任何不良单词。例如,若rob是不良单词,那么文本problem含有不良单词。
(2)字符串最长公共前缀
Trie树利用多个字符串的公共前缀来节省存储空间,反之,当我们把大量字符串存储到一棵trie树上时,我们可以快速得到某些字符串的公共前缀。
举例:
给出N 个小写英文字母串,以及Q 个询问,即询问某两个串的最长公共前缀的长度是多少?
解决方案:首先对所有的串建立其对应的字母树。此时发现,对于两个串的最长公共前缀的长度即它们所在结点的公共祖先个数,于是,问题就转化为了离线(Offline)的最近公共祖先(Least Common Ancestor,简称LCA)问题。
而最近公共祖先问题同样是一个经典问题,可以用下面几种方法:
1. 利用并查集(Disjoint Set),可以采用采用经典的Tarjan 算法;
2. 求出字母树的欧拉序列(Euler Sequence )后,就可以转为经典的最小值查询(Range Minimum Query,简称RMQ)问题了;
(3)排序
Trie树是一棵多叉树,只要先序遍历整棵树,输出相应的字符串便是按字典序排序的结果。
比如给你N 个互不相同的仅由一个单词构成的英文名,让你将它们按字典序从小到大排序输出。
(4) 作为其他数据结构和算法的辅助结构
如后缀树,AC自动机等
(5)词频统计
trie树在这里的应用类似哈夫曼树,
比如词频统计使用哈希表或者堆都可以,但是如果内存有限,就可以用trie树来压缩空间,因为trie树的公共前缀都是用一个节点保存的。
(6)字符串搜索的前缀匹配
trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。
Trie树检索的时间复杂度可以做到n,n是要检索单词的长度,
如果使用暴力检索,需要指数级O(N2)的时间复杂度。
参考:
字典树(Trie树)的实现及应用的更多相关文章
- [POJ] #1002# 487-3279 : 桶排序/字典树(Trie树)/快速排序
一. 题目 487-3279 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 274040 Accepted: 48891 ...
- Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结
Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- [转载]字典树(trie树)、后缀树
(1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边 ...
- Luogu P2922 [USACO08DEC]秘密消息Secret Message 字典树 Trie树
本来想找\(01Trie\)的结果找到了一堆字典树水题...算了算了当水个提交量好了. 直接插入模式串,维护一个\(Trie\)树的子树\(sum\)大小,求解每一个文本串匹配时走过的链上匹配数和终点 ...
- 字典树 trie树 学习
一字典树 字典树,又称单词查找树,Trie树,是一种树形结构,哈希表的一个变种 二.性质 根节点不包含字符,除根节点以外的每一个节点都只包含一个字符: 从根节点到某一节点,路径上经过的字符串连接起 ...
- 【字符串算法】字典树(Trie树)
什么是字典树 基本概念 字典树,又称为单词查找树或Tire树,是一种树形结构,它是一种哈希树的变种,用于存储字符串及其相关信息. 基本性质 1.根节点不包含字符,除根节点外的每一个子节点都包含一个字符 ...
- 字典树 Trie树
什么是Trie树? 形如 其中从根节点到红色节点的路径上的字母所连成的字符串即为一个Trie树上所存的字符串. 比如,这个trie树上有ab,abc,bd,dda这些字符串. 至于怎么构建和查找或添加 ...
随机推荐
- mvc中EditorFor TextBoxFor什么区别
EditorFor 是映射到Model 属性上面,忽略用户自定义属性和样式 Model 可以为nullTextBoxFor是映射到Model 属性上面,可以用户自定义属性和样式 Model 不可以为n ...
- 在微信中实现app软件中账号注册的功能实现
利用写好的接口url地址访问 输入手机号,接收手机验证码 <span class="accept" >点击获取验证码</span> $(".acc ...
- JavaScript 技巧总结
日期1. 日期时间戳 +new Date() = new Date().getTime() 数组1. 类数组转数组 var arr = Array.prototype.slice.call(argum ...
- php-fpm.conf两个至关重要的参数
这里规定了PHP-CGI的连接.发送和读取的时间,300秒足够用了,因此我的服务器很少出现504 Gateway Time-out这个错误.最关键的是php-fpm.conf的设置,这个会直接导致50 ...
- dns (域名系统)
dns (域名系统) DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP ...
- cad2013
## ribbon界面? ribbon界面是一种设计ui, 可以认为是传统的 菜单和工具栏 组合. 是 用于 实时显示 + 面向结果的 设计ui 但并不是所有的程序都适合. ribbon 并不是 ...
- TCP/IP网络编程技术基础
零零碎碎记下点→ 不对的欢迎大家批评纠正→ 以免本人及偶尔看到此博客的人继续迷途未返→ >>>>>基础知识→ 1→TCP/IP英文名:Tranmission Contro ...
- [Effective JavaScript 笔记]第53条:保持一致的约定
对于api使用者来说,你所使用的命名和函数签名是最能产生普遍影响的决策.这些约定很重要具有巨大的影响力.它建立了基本的词汇和使用它们的应用程序的惯用法.库的使用者必须学会阅读和使用这些.一致的约定可以 ...
- ZeroMQ(java)中对IO的封装(StreamEngine)
哎,各种各样杂七杂八的事情...好久没有看代码了,其实要搞明白一个与IO相关的框架,最好的办法就是把它的I/0的读写两个过程搞清楚...例如在netty中,如果能将eventLoop的运行原理搞清楚, ...
- linux下cp目录时排除一个或者多个目录的方法
说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录里面除过e目录之外的所有目录拷贝到/bak目录中 系统运维 www.osyunwei.com ...