原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

Trie树(字典树)

一、引入

字典是干啥的?查找字的。

字典树自然也是起查找作用的。查找的是啥?单词。

看以下几个题:

1、给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。

答:简单!map,短小精悍。

好。下一个

2、给出n个单词和m个询问,每次询问一个前缀,回答询问是多少个单词的前缀。

答:map,把每个单词拆开。

judge:n<=200000,TLE!

这就需要一种高级数据结构——Trie树(字典树)

二、原理

在本篇文章中,假设所有单词都只由小写字母构成

对cat,cash,app,apple,aply,ok 建一颗字典树,建成之后如下图所示

由此可以看出:

1、字典树用边表示字母

2、有相同前缀的单词公用前缀节点,那我们可以的得出每个节点最多有26个子节点(在单词只包含小写字母的情况下)

3、整棵树的根节点是空的。为什么呢?便于插入和查找,这将会在后面解释。

4、每个单词结束的时候用一个特殊字符表示,图中用的‘′,那么从根节点到任意一个‘′,那么从根节点到任意一个‘’所经过的边的所有字母表示一个单词。

三、基本操作

A、insert,插入一个单词

1.思路

从图中可以直观看出,从左到右扫这个单词,如果字母在相应根节点下没有出现过,就插入这个字母;否则沿着字典树往下走,看单词的下一个字母。

这就产生一个问题:往哪儿插?计算机不会自己选择位置插,我们需要给它指定一个位置,那就需要给每个字母编号。

我们设数组trie[i][j]=k,表示编号为i的节点的第j个孩子是编号为k的节点。

什么意思呢?

这里有2种编号,一种是i,k表示节点的位置编号,这是相对整棵树而言的;另一种是j,表示节点i的第j的孩子,这是相对节点i而言的。

不理解?看图

还是单词cat,cash,app,apple,aply,ok

我们就按输入顺序对其编第一种号,红色表示编号结果。因为先输入的cat,所以c,a,t分别是1,2,3,然后输入的是cash,因为c,a是公共前缀,所以从s开始编,s是4,以此类推。

注意这里相同字母的编号可能不同

第二种编号,相对节点的编号,紫色表示编号结果。

因为每个节点最多有26个子节点,我们可以按他们的字典序从0——25编号,也就是他们的ASCLL码-a的ASCLL码。

注意这里相同字母的编号相同

实际上每个节点的子节点都应该从0编到——25,但这样会发现许多事根本用不到的。比如上图的根节点应该分出26个叉。节约空间,用到哪个分哪个。

这样编号有什么用呢?

回到数组trie[i][j]=k。 数组trie[i][j]=k,表示编号为i的节点的第j个孩子是编号为k的节点。

那么第二种编号即为j,第一种编号即为i,k

2、代码

void insert()//插入单词s
{
len=strlen(s);//单词s的长度
root=0;//根节点编号为0
for(int i=0;i<len;i++)
{
int id=s[i]-'a';//第二种编号
if(!trie[root][id])//如果之前没有从root到id的前缀
trie[root][id]=++tot;//插入,tot即为第一种编号
root=trie[root][id];//顺着字典树往下走
}
}

B、search,查找

查找有很多种,可以查找某一个前缀,也可以查找整个单词。

再次我们以查找一个前缀是否出现过为例讲解

1、思路

从左往右以此扫描每个字母,顺着字典树往下找,能找到这个字母,往下走,否则结束查找,即没有这个前缀;前缀扫完了,表示有这个前缀。

2、代码

bool find()
{
len=strlen(s);
root=0;//从根结点开始找
for(int i=0;s[i];i++)
{
int x=s[i]-'a';//
if(trie[root][x]==0) return false;//以root为头结点的x字母不存在,返回0
root=trie[root][x];//为查询下个字母做准备,往下走
}
return true;//找到了
}

3、如果是查询某个单词的话,我们用bool变量 v[i]表示节点i是否是单词结束的标志。

那么最后return的是v[root],所以在插入操作中插入完每个单词是,要对单词最后一个字母的v[i]置为true,其他的都是false

4、如果是查询前缀出现的次数的话,那就在开一个sum[],表示位置i被访问过的次数,

那么最后return的是sum[root],插入操作中每访问一个节点,都要让他的sum++

这里前缀的次数是标记在前缀的最后一个字母所在位置的后一个位置上。

比如:前缀abc出现的次数标记在c所在位置的后一个位置上,

五、模板题

hud 1251 统计难题 http://acm.hdu.edu.cn/showproblem.php?pid=1251

codevs 4189 字典 http://codevs.cn/problem/4189/

[转] 浅谈Trie树(字典树)的更多相关文章

  1. (转)浅谈trie树

    浅谈Trie树(字典树)         Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问 ...

  2. 剑指Offer——Trie树(字典树)

    剑指Offer--Trie树(字典树) Trie树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种的单词.对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位 ...

  3. AC自动机——1 Trie树(字典树)介绍

    AC自动机——1 Trie树(字典树)介绍 2013年10月15日 23:56:45 阅读数:2375 之前,我们介绍了Kmp算法,其实,他就是一种单模式匹配.当要检查一篇文章中是否有某些敏感词,这其 ...

  4. Trie(字典树)

    没时间整理了,老吕又讲课了@ @ 概念 Trie即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种,典型应用是统计和排序大量的字符串(不限于字符串) Trie字典树主要用于存储字符串, ...

  5. 9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚 ...

  6. 浅谈Trie

    所谓\(Trie\)就是字典树. 何为字典树?想象一下我们平时用拼音查字法在字典树查汉字的时候,一位一位确定这个汉字的拼音从而翻到我们想要看的那一面. 所以\(Trie\)树跟字典一样,是一种逐位检索 ...

  7. 浅谈Trie树(字典树)

          Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单 ...

  8. 浅谈 trie树 及其实现

    定义:又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构, 如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. 核心思想:是空间换时间.利用字符串的公共前缀来降低查询时间的开 ...

  9. 浅谈Trie树

    Trie树,也叫字典树.顾名思义,它就是一个字典 字典是干什么的?查找单词!(英文字典哦) 个人认为字典树这个名字起得特别好,因为它真的跟字典特别像,一会r你就知道了. 注:trie的中文翻译就是单词 ...

随机推荐

  1. CodeForces1051E EXKMP + 线段树dp

    http://codeforces.com/problemset/problem/1051/E 题意:给你一个很大的数字,然后你可以把这个数字拆分成为任意多个部分,要求每一个部分的数字大小要在一个区间 ...

  2. Storm 消息分发策略

    1.Shuffle Grouping:随机分组,随机派发stream里面的tuple,保证每个bolt接收到的tuple数目相同.2.Fields Grouping:按字段分组,比如按userid来分 ...

  3. redis做session会话共享

    项目中需要两个不同的web项目互相访问,用户对象为同一个User.决定用Redis来存储用户对象信息...ok,环境搭建开始: 1.pom.xml引入Redis依赖的jar: <!-- jedi ...

  4. RelativeLayout中include 控件覆盖重叠的问题

    RelativeLayout直接include另一个layout是会把include中的控件与当前layout中的控件覆盖重叠,经过查资料 其中的include标签一定要加上(因为include中不指 ...

  5. LeetCode(194.Transpose File)(awk进阶)

    194. Transpose File Given a text file file.txt, transpose its content. You may assume that each row ...

  6. Jsp的四大作用域与九大对象

    内置对象特点: 1. 由JSP规范提供,不用编写者实例化. 2. 通过Web容器实现和管理 3. 所有JSP页面均可使用 4. 只有在脚本元素的表达式或代码段中才可使用(<%=使用内置对象%&g ...

  7. 060、在docker中使用flannel(2019-03-29 周五)

    参考https://www.cnblogs.com/CloudMan6/p/7441188.html   配置docker 连接flannel   编辑host1的docker配置文件/etc/sys ...

  8. tedu训练营day01

    1.三大操作系统 1.Unix :MacOS 2.Linux :Ubuntu18.04 .CentOS.RedHat 3.Windows :Win7.Win8.Win102.VMware Workst ...

  9. SpringBoot系列: 理解 Spring 的依赖注入(二)

    ==============================Spring 容器中 Bean 的名称==============================声明 bean 有两个方式, 一个是 @B ...

  10. JAVA正确地自定义比较对象---如何重写equals方法和hashCode方法

    在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city. public class Address { priva ...