算法 | 动画+解析,轻松理解「Trie树」
Trie这个名字取自“retrieval”,检索,因为Trie可以只用一个前缀便可以在一部字典中找到想要的单词。
虽然发音与「Tree」一致,但为了将这种 字典树 与 普通二叉树 以示区别,程序员小吴一般读「Trie」尾部会重读一声,可以理解为读「TreeE」。
Trie 树,也叫“字典树”。顾名思义,它是一个树形结构。它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题。
此外 Trie 树也称前缀树(因为某节点的后代存在共同的前缀,比如pan是panda的前缀)。
它的key都为字符串,能做到高效查询和插入,时间复杂度为O(k),k为字符串长度,缺点是如果大量字符串没有共同前缀时很耗内存。
它的核心思想就是通过最大限度地减少无谓的字符串比较,使得查询高效率,即「用空间换时间」,再利用共同前缀来提高查询效率。
Trie树的特点
假设有 5 个字符串,它们分别是:code,cook,five,file,fat。现在需要在里面多次查找某个字符串是否存在。如果每次查找,都是拿要查找的字符串跟这 5 个字符串依次进行字符串匹配,那效率就比较低,有没有更高效的方法呢?
如果将这 5 个字符串组织成下图的结构,从肉眼上扫描过去感官上是不是比查找起来会更加迅速。

Trie树样子
通过上图,可以发现 Trie树 的三个特点:
根节点不包含字符,除根节点外每一个节点都只包含一个字符
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串
每个节点的所有子节点包含的字符都不相同
通过动画理解 Trie 树构造的过程。在构造过程中的每一步,都相当于往 Trie 树中插入一个字符串。当所有字符串都插入完成之后,Trie 树就构造好了。

Trie 树构造
Trie树的插入操作
Trie树的插入操作
Trie树的插入操作很简单,其实就是将单词的每个字母逐一插入 Trie树。插入前先看字母对应的节点是否存在,存在则共享该节点,不存在则创建对应的节点。比如要插入新单词 cook,就有下面几步:
插入第一个字母 c,发现 root 节点下方存在子节点 c,则共享节点 c
插入第二个字母 o,发现 c 节点下方存在子节点 o,则共享节点 o
插入第三个字母 o,发现 o 节点下方不存在子节点 o,则创建子节点 o
插入第三个字母 k,发现 o 节点下方不存在子节点 k,则创建子节点 k
至此,单词 cook 中所有字母已被插入 Trie树 中,然后设置节点 k 中的标志位,标记路径 root->c->o->o->k 这条路径上所有节点的字符可以组成一个单词cook
Trie树的查询操作
在 Trie 树中查找一个字符串的时候,比如查找字符串 code,可以将要查找的字符串分割成单个的字符 c,o,d,e,然后从 Trie 树的根节点开始匹配。如图所示,绿色的路径就是在 Trie 树中匹配的路径。

code的匹配路径
如果要查找的是字符串 cod(鳕鱼)呢?还是可以用上面同样的方法,从根节点开始,沿着某条路径来匹配,如图所示,绿色的路径,是字符串 cod 匹配的路径。但是,路径的最后一个节点「d」并不是橙色的,并不是单词标志位,所以 cod 字符串不存在。也就是说,cod是某个字符串的前缀子串,但并不能完全匹配任何字符串。

cod的匹配路径
程序员不要当一条咸鱼,要向 cook 靠拢:)
Trie树的删除操作
Trie树的删除操作与二叉树的删除操作有类似的地方,需要考虑删除的节点所处的位置,这里分三种情况进行分析:
删除整个单词(比如hi)

删除整个单词
从根节点开始查找第一个字符h
找到h子节点后,继续查找h的下一个子节点i
i是单词hi的标志位,将该标志位去掉
i节点是hi的叶子节点,将其删除
删除后发现h节点为叶子节点,并且不是单词标志位,也将其删除
这样就完成了hi单词的删除操作
删除前缀单词(比如cod)

删除前缀单词
这种方式删除比较简单。
只需要将cod单词整个字符串查找完后,d节点因为不是叶子节点,只需将其单词标志去掉即可。
删除分支单词(比如cook)

删除分支单词
与 删除整个单词 情况类似,区别点在于删除到 cook 的第一个 o 时,该节点为非叶子节点,停止删除,这样就完成 cook 字符串的删除操作。
Trie树的应用
事实上 Trie树 在日常生活中的使用随处可见,比如这个:
具体来说就是经常用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
1. 前缀匹配
例如:找出一个字符串集合中所有以 五分钟 开头的字符串。我们只需要用所有字符串构造一个 trie树,然后输出以 五−>分−>钟 开头的路径上的关键字即可。
trie树前缀匹配常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。

google搜索
2. 字符串检索
给出 N 个单词组成的熟词表,以及一篇全用小写英文书写的文章,按最早出现的顺序写出所有不在熟词表中的生词。
检索/查询功能是Trie树最原始的功能。给定一组字符串,查找某个字符串是否出现过,思路就是从根节点开始一个一个字符进行比较:
如果沿路比较,发现不同的字符,则表示该字符串在集合中不存在。
如果所有的字符全部比较完并且全部相同,还需判断最后一个节点的标志位(标记该节点是否代表一个关键字)。
Trie树的局限性
如前文所讲,Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
假设字符的种数有 m 个,有若干个长度为n的字符串构成了一个 Trie 树 ,则每个节点的出度为 m(即每个节点的可能子节点数量为 m),Trie 树的高度为 n。很明显我们浪费了大量的空间来存储字符,此时 Trie 树的最坏空间复杂度为 O(m^n)。也正由于每个节点的出度为 m,所以我们能够沿着树的一个个分支高效的向下逐个字符的查询,而不是遍历所有的字符串来查询,此时 Trie 树的最坏时间复杂度为 O(n)。
这正是空间换时间的体现,也是利用公共前缀降低查询时间开销的体现。
(*本文为作者投稿文章,转载请联系作者)
公开课预告
◆
强化学习
◆
本课程是一次理论+实战的结合,将重点介绍强化学习的模型原理以及A3C模型原理,最后通过实践落实强化学习在游戏中的应用。
推荐阅读:
BAT七年经验,却抵不过外企面试的两道算法题?
刘铁岩谈机器学习:随波逐流的太多,我们需要反思
Python爬取爱奇艺腾讯视频250,000条数据分析为什么李诞不值得了?
这个用Python编写的PDF神器你值得拥有!
云计算演进历程与模式 - 初识云计算知识专栏(2)
“iPhone 3 年内必死!”
数据库的 N 多骚操作了解一下?
25k~60k, 疯狂裁员的背后, 技术人才需求依然旺盛, 快来投简历
老程序员肺腑忠告:千万别一辈子靠技术生存!
相关文章:

#Ruby# Introspect (2)
3. Looking at Classes superclass > get the parent of any particular class ancestors > get both superclasses and mixin modules 在Ruby1.9中,任何未指定的class都继承自Object,而Object继承自BasicObject,BasicObject无supercla…

国内ITSM解决方案-UNIPER
UNIPER是行业领先的ITSM解决方案提供商。参与了ITIL V3的开发与实践,是中国ITSM行业推动者之一,方案包括服务台,事件和问题管理,变更和配置管理,服务等级管理,IT运营绩效考评,主动计划任务管理&…

清华首批7门标杆课程,到底有多牛?
整理 | Jane出品 | AI科技大本营近日,清华大学公布首批七门标杆课程。什么是标杆课程?据清华大学官方介绍,此项评选是 2018 年 4 月启动的,由各院系推荐、教务处形式审查。本次最终确定了 26 门课程参加评审,并于 2018…

我的Rails笔记(1)
《Agile Web Development With Rails》Notebook. 环境: Rails 3.1.0 Gem 1.8.10 Ruby ruby 1.9.2p180 1. rails depot 2. rails generate scaffold Product title:string description:text image_url:string price:decimal 报错:/1.9.1/gems/execj…

资源 | 斯坦福最新NLP课程上线,选择PyTorch放弃TensorFlow
整理 | Jane 出品 | AI科技大本营 今天在斯坦福大学 2019 年冬季 CS224n 最新课程已经正式更新到官网啦。新一年,大家可以开始跟着名校课程学起来啦~今年一个非常大的变化就是所有内容实现都使用 PyTorch,不再使用 TensorFlow。内容设计方面新增了 Tra…

推荐本人微博及浅谈发博原则
本人新浪微博:http://weibo.com/jinbinforever 花了一些力气,将关注数降到100以下,以后原则上关注数不会增加了。发现这样做的好处非常明显,减少了很多无谓的信息干扰。less is more,做减法能让自己收获更多࿰…

Lintcode108 Palindrome Partitioning || solution 题解
【题目描述】Given a strings, cutsinto some substrings such that every substring is a palindrome.Return the minimum cuts needed for a palindrome partitioning ofs.给定一个字符串s,将s分割成一些子串,使每个子串都是回文。返回s符合要求的的最…

发现价值(1)-无限的网络资源
Google发布Google wave的新闻甚嚣尘上.匆匆忙忙间,我也第一时间浏览了这个未来的杀手级应用.不得不赞叹Google强大创新力的同时,又不得不在自己的 to-read-list 上多了一个标签. 仅仅是read是不能产生任何价值的,对于技术我们需要dive into it.这点我明白,但是还是常常陷入浩如…

Ruby的Singleton method
Ruby中,特定于某一对象的方法被称为Singleton method。 例如: a "string"def a.runputs "#{self} run" endstr.run # >#string run run方法是特定于a这个对象的,故run方法是a的Singleton方法。 实现上,当…
AD ---- 活动目录的日常管理操作
管理信任关系:什么是信任关系:信任关系是用于确保一个域的用户可以访问和使用另一个域中资源的安全机制 根据传递性分,信任关系可分为可传递信任关系和不可传递信任关系两种 根据域之间关系分,Windows信任关系则可分为四种 信任关系是如何工作的 创建信任关系 删除信任关系 …

07.GitHub实战系列~7.Git之VS2013团队开发(如果不想了解git命令直接学这篇即可)...
GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html —————————————————————————————————————————————————————— 直接实战~(如果你之前安装了git其他版本都可以卸载了~这个就够了…

公开课报名 | 深入浅出理解A3C强化学习
强化学习是一种比较传统的人工智能手段,在近年来随着深度学习的发展,强化学习和深度学习逐渐结合在了一起。这种结合使得很多原来无法想象的工作有了可能,最令我们瞩目的莫过于AlphaGo战胜李世石,以及OpenAI团队的机器人可以在团战…

Hibernate是啥?
1:Hibernate和JDBC、ODBC的作用是一样的、用来访问、操作数据库的。它的优势在哪?没用过、我也不知道。。。不过貌似【数据持久化】是个关键词。[下边是百科里的一段话:对象上数据的修改,Hibernate框架会把这种修改同步到数据库中…

#Java夜未眠# 读书笔记
微博上的蔡学镛是个有趣的家伙,有条微博这样写道: “记得十多年前我的第一本书出版时,我隔几天就到书店微服出巡,看看状况。当看到有人拿起我的书时,我内心的口白:"英明英明,你可真识货呀…

asp.net 控制页面css样式
asp.net 控制页面css样式fontDiv.Style["display"] "none";fontDiv.Style["display"] "";转载于:https://www.cnblogs.com/qiantuwuliang/archive/2009/06/02/1494709.html

腾讯AI Lab负责人张潼离职,张正友或接替其位
来源 | 网易智能 刚刚,据知情人士透露,腾讯人工智能实验室 AI Lab 主任张潼已经从腾讯离职,未来将重返学术界。 关于该消息,腾讯方面目前尚无回应。 网易智能独家获悉,AI Lab接手人是机器人实验室的张正友。 有消息…

频频霸榜的Python,竟遭开发者嫌弃!
在刚刚过去的 2018 年里,要说最热门的科技领域是哪一个?毋庸置疑的是,人工智能必排在前列;而要论编程语言界,最流行的编程语言是谁?那非 Python 莫属。2018 年 8 月,根据一年一度的 IEEE Spectr…

#每天一种设计模式# 观察者模式
系统常常会出现这种情况: 每一个部分需要知道整体的状态。比如Excel中,当你修改了一个单元格的值,可能横列的sum需要改变,纵列的sum需要改变,根据这个单元格做的图需要改变,是否被修改的按钮需要激活... 如…

el-input怎么绑定回车事件
在 Vue 2.0 中,为自定义组件绑定原生事件必须使用 .native 修饰符:<el-input v-model"queryForm.skuName" placeholder"请输入商品名称" keyup.enter.native"skuNameSearch"></el-input> 转载于:https://www.…

DOS命令大全(经典收藏)
http://wuhua.javaeye.com/blog/32374 net use \\ip\ipc$ " " /user:" " 建立IPC空链接 net use \\ip\ipc$ "密码" /user:"用户名" 建立IPC非空链接 net use h: \\ip\c$ "密码" /user:"用户名" 直接登陆后映射对…

Ruby Metaprogramming
Ruby使用者对attr_accessor一定不会陌生。 class Aattr_accessor :num end 等效于: class Adef numnumenddef (value)num valueend end 在类的定义中,attr_accessor定义了num的读写方法,只用了一行代码就生成了两个实例方法,很…

四川大学线下编程比赛第一题:数字填充
四川大学线下编程比赛第一题:数字填充公布公司:有 效 期:CSDN 2014-09-27至2015-09-26 难 度 等 级:答 题 时 长:编程语言要求:120分钟C C Java C#题目详情peter喜欢玩数字游戏。但数独这种游戏对他来说太简…

Google AI骗过了Google,工程师竟无计可施?
作者 | 若名 出品 | AI科技大本营 如果你通过 Google 搜索购买演唱会门票或者注册论坛账号,系统会提示你必须点击几个图框、音频或者移动鼠标等操作来确认是人类在操作验证而不是机器人。 其背后的验证机制就是 CAPTCHA(验证码),…

用高中数学理解AI “深度学习”的基本原理
本文作者尚俊霖,全职产品经理,业余自学机器学习。最近开始写硬核科普,欢迎关注公众号欠拟合(ID:Underfit)。Google 研发了十年自动驾驶后,终于在本月上线了自动驾驶出租车服务。感谢“深度学习”技术&#…

Linux I2C工具查看配置I2C设备【转】
转自:http://blog.chinaunix.net/uid-26895763-id-3478882.html 在處理音訊相關的問題時,我通常會找個方法來讀寫codec中register的值。幸好linux上也有這樣的工具 – i2c tools。先到lm-sensors下載soure code,然後cross compile成arm的執行…

Ruby之类定义
介绍几种不常见的类定义方法: 1. Struct PersonStruct.new(:name,:age,:sex)pPerson.new("liyuchun")puts p Struct生成一个仅仅包含数据属性的类。但是你可以在这个类的基础上扩展: PersonStruct.new(:name,:age,:sex)class Persondef …

引用 引用 引用 学会求知 学会共处 学会做人 学会做事
◆学历不等于能力和水平,学校学到的在社会能用上的只有15%,而在社会能学到85%。◆世上很多发生的事必有其原因,必有其结果,必有其收获。◆心态归零,天道酬勤。◆老板是私营企业家,赚了小钱是自己的…

python写一个通讯录step by step V3.0
python写一个通讯录step by step V3.0 更新功能: 数据库进行数据存入和读取操作 字典配合函数调用实现switch功能 其他:函数、字典、模块调用 注意问题: 1、更优美的格式化输出 2、把日期换算成年龄 3、更新操作做的更优雅 准备工作 db准备…

#每天一种设计模式# 模板方法
《松本行弘的程序世界》对模板方法(Template method)的说明非常清晰: 在父类的一个方法中定义算法的框架,其中几个步骤的具体内容则留给子类来实现。 比如一个用于公司欢迎同事的程序: class Adef initializename "jinbin"word …

如何更好地玩转GitHub?
本文作者黄昱俊,国资企业投资部总经理,主要负责投资部门建设、投资流程管理、投后资源管理。历经10年,从医疗器械研发工程师到投资管理的蜕变,业余尝试ETF量化投资。 本文介绍如何在GitHub上更新Fork以及PullRequest给源项目。 在…