原文地址: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. loadrunner / socket level data and wininet level data

    s loadrunner录制脚本时,此网站证书无效/无法录制到脚本问题解决 http://www.51testing.com/html/64/497364-3569552.html lr录制后空白_l ...

  2. Matlab2017A破解版安装详细图文教程(附破解补丁) 64位

    摘录网址:http://www.jb51.net/softjc/543170.html MATLAB2017a安装教程: 1.下载并解压本站提供的MATLAB2017a破解版安装包,载入右键解压或者使 ...

  3. vue @blur v-model数据没有更新问题

    今天遇到一个问题,是一个输入框绑定了一个失去焦点事件,要发送一个客户填写的数据给后台查询然后拿到返回值把它渲染到页面上,但是从后台获取到的数据却没有在页面上渲染出来,console.log打印时显示数 ...

  4. Sublime Text3中 less 自动编译成 css 的方法

    使用sublime text的less2css插件 步骤: 1.安装node.js,这个到官网下载即可 2.安装less,方法:命令行输入: npm install -g less 3.sublime ...

  5. [C#]一个简易的、轻量级的方法并行执行线程辅助类

      一个简易的.轻量级的方法并行执行线程辅助类 在实际应用中,经常要让多个方法并行执行以节约运行时间,线程就是必不可少的了,而多线程的管理经常又是一件头疼的事情,比如方法并行执行异步的返回问题,方法并 ...

  6. Spark常见问题汇总

    原文地址:https://my.oschina.net/tearsky/blog/629201 摘要: 1.Operation category READ is not supported in st ...

  7. [Android] Android利用Coordinatorlayout+AppbarLayout实现折叠式布局

    折叠式布局在App中相当常见,给人一种科技感,充满良好的用户体验. 本文就以两个简单的例子,来举例说明基本折叠式布局: 首先需要在app/build.gradle下添加如下依赖: compile 'c ...

  8. python实现双向链表

    双向链表 一种更复杂的链表是“双向链表”或“双面链表”.每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值:而另一个指向下一个节点,当此节点为最后一个节点时,指向空值. 实现 c ...

  9. Java - 网络编程完全总结

    本文主要是自己在网络编程方面的学习总结,先主要介绍计算机网络方面的相关内容,包括计算机网络基础,OSI参考模型,TCP/IP协议簇,常见的网络协议等等,在此基础上,介绍Java中的网络编程. 一.概述 ...

  10. Android MediaPlayer播放raw资源封装类

    import android.content.Context; import android.media.MediaPlayer; import xxxx.R; public class MediaU ...