字典树

数据结构——从英文字典树到中文字典树 昨天面试电话中的一道题,题目如下:给你一个姓名的集合,查找你的名字是否在里面出现,比如搜索姓氏为叶的人,那么会出现所有姓为叶的人,应该如何设计? 当时的回答是,姓为key,名为value,存放到multimap中,使用multimap中的count函数统计key为叶的个数,然后用find函数找到第一个key为叶的指针,使用迭代器从该指针向后查找count个元素,判断这count个元素中是否有姓名 阅读详情

第一部分、Trie树

1.1、什么是Trie树

    Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

    Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

它有3个基本性质:

  1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
  2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符都不相同。

1.2、树的构建

举个在网上流传颇广的例子,如下:
    题目:给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置。
    分析:这题当然可以用hash来解决,但是本文重点介绍的是trie树,因为在某些方面它的用途更大。比如说对于某一个单词,我们要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。
    现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以b,c,d,f之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b作为第二个字母的,一次次缩小范围和提高针对性,这样一个树的模型就渐渐清晰了。
    好比假设有b,abc,abd,bcd,abcd,efg,hii 这6个单词,我们构建的树就是如下图这样的:
  当时第一次看到这幅图的时候,便立马感到此树之不凡构造了。单单从上幅图便可窥知一二,好比大海搜人,立马就能确定东南西北中的到底哪个方位,如此迅速缩小查找的范围和提高查找的针对性,不失为一创举。
    ok,如上图所示,对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为 红色,就表示这个单词存在,否则不存在。
    那么,对于一个单词,我只要顺着他从根走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。
    这样一来我们查询和插入可以一起完成(重点体会这个查询和插入是如何一起完成的,稍后,下文具体解释),所用时间仅仅为单词长度,在这一个样例,便是10。
    我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。

1.3、前缀查询

    上文中提到”比如说对于某一个单词,我们要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单“。下面,咱们来看看这个前缀查询问题:
    已知n个由小写字母构成的平均长度为10的单词,判断其中 是否存在某个串为另一个串的前缀子串。下面对比3种方法:
  1. 最容易想到的:即从字符串集中从头往后搜,看每个字符串是否为字符串集中某个字符串的前缀,复杂度为O(n^2)。
  2. 使用hash:我们用hash存下所有字符串的所有的前缀子串,建立存有子串hash的复杂度为O(n*len),而查询的复杂度为O(n)* O(1)= O(n)。
  3. 使用trie:因为当查询如字符串abc是否为某个字符串的前缀时,显然以b,c,d....等不是以a开头的字符串就不用查找了。所以建立trie的复杂度为O(n*len),而建立+查询在trie中是可以同时执行的,建立的过程也就可以成为查询的过程,hash就不能实现这个功能。所以总的复杂度为O(n*len),实际查询的复杂度也只是O(len)。(说白了,就是Trie树的平均高度h为len,所以Trie树的查询复杂度为O(h)=O(len)。好比一棵二叉平衡树的高度为logN,则其查询,插入的平均时间复杂度亦为O(logN))。
    下面解释下上述方法3中所说的为什么hash不能将建立与查询同时执行,而Trie树却可以:
  • 在hash中,例如现在要输入两个串911,911456,如果要同时查询这两个串,且查询串的同时若hash中没有则存入。那么,这个查询与建立的过程就是先查询其中一个串911,没有,然后存入9、91、911;而后查询第二个串911456,没有然后存入9、91、911、9114、91145、911456。因为程序没有记忆功能,所以并不知道911在输入数据中出现过,只是照常以例行事,存入9、91、911、9114、911...。也就是说用hash必须先存入所有子串,然后for循环查询。
  • 而trie树中,存入911后,已经记录911为出现的字符串,在存入911456的过程中就能发现而输出答案;倒过来亦可以,先存入911456,在存入911时,当指针指向最后一个1时,程序会发现这个1已经存在,说明911必定是某个字符串的前缀。
     读者反馈@悠悠长风: 关于这点,我有不同的看法。hash也是可以实现边建立边查询的啊。当插入911时,需要一个额外的标志位,表示它是一个完整的单词。在处理911456时,也是按照前面的查询9,91,911,当查询911时,是可以找到前面插入的911,且通过标志位知道911为一个完整单词。那么就可以判断出911为911456的前缀啊。虽然trie树更适合这个问题,但是我认为hash也是可以实现边建立,边查找。
    至于,有关Trie树的查找,插入等操作的实现代码,网上遍地开花且千篇一律,诸君尽可参考,想必不用我再做多余费神。

1.4、查询

    Trie树是简单但实用的数据结构,通常用于实现字典查询。我们做即时响应用户输入的AJAX搜索框时,就是Trie开始。本质上,Trie是一颗存储多个字符串的树。相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串。和普通树不同的地方是,相同的字符串前缀共享同一条分支。下面,再举一个例子。给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie:
  可以看出:
  • 每条边对应一个字母。
  • 每个节点对应一项前缀。叶节点对应最长前缀,即单词本身。
  • 单词inn与单词int有共同的前缀“in”, 因此他们共享左边的一条分支,root->i->in。同理,ate, age, adv, 和ant共享前缀"a",所以他们共享从根节点到节点"a"的边。
    查询操纵非常简单。比如要查找int,顺着路径i -> in -> int就找到了。

    搭建Trie的基本算法也很简单,无非是逐一把每则单词的每个字母插入Trie。插入前先看前缀是否存在。如果存在,就共享,否则创建对应的节点和边。比如要插入单词add,就有下面几步:
  1. 考察前缀"a",发现边a已经存在。于是顺着边a走到节点a。
  2. 考察剩下的字符串"dd"的前缀"d",发现从节点a出发,已经有边d存在。于是顺着边d走到节点ad
  3. 考察最后一个字符"d",这下从节点ad出发没有边d了,于是创建节点ad的子节点add,并把边ad->add标记为d。

1.5、Trie树的应用

    除了本文引言处所述的问题能应用Trie树解决之外,Trie树还能解决下述问题(节选自此文: 海量数据处理面试题集锦与Bit-map详解):
  • 3、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
  • 9、1000万字符串,其中有些是重复的,需要把重复的全部去掉,保留没有重复的字符串。请怎么设计和实现?
  • 10、 一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。
  • 13、寻找热门查询:搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前有一千万个记录,这些查询串的重复读比较高,虽然总数是1千万,但是如果去除重复和,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就越热门。请你统计最热门的10个查询串,要求使用的内存不能超过1G。
    (1) 请描述你解决这个问题的思路;
    (2) 请给出主要的处理流程,算法,以及算法的复杂度。
    有了Trie,后缀树就容易理解了。本文接下来的第二部分,介绍后缀树。

字典树实现词频统计 字典树实现词频统计 Trie树(字典树) 字典树又叫前缀树,是处理字符串常用的数据结构,最近和朋友一起粗略写了一下关于字典树的词频统计。 一、功能介绍 文件流读写单词; 将读到的单词插入树中; 打印树,打印出单词和个数以及词频; 单个单词的个数和频率查询功能; 销毁字典树(释放内存); 结构体代码 typedef struct TrieNode { unsigned long count; //该结点终结的单词个数 struct TrieNode* next[26]; //下标 0-25 分别表示 a 阅读详情

相关推荐

【原创】字典树的五种实现方式

字典树(trie树),是一种前缀树,可以在O(m)的时间复杂度匹配目标字符串(m为目标字符串的长度),字典树广泛应用在NLP领域作为词典,具体应用有:分词、词频统计、字符串查询、字符串排序等。 虽然字典树有较低的时间复杂度,但当词典较大时(如中文分词词典),字典树占用的空间非常大,常常难以满足工业应用的需求,因此需要在保持字典树优异的时间复杂度的前提下,尽可能的优化字典树的空间。本文由浅入深,讲解经典字典树、链表字典树、Hash表字典树、双数组字典树、单数组字典树5种字典树实现及各种实现的优缺点。 经典字典

suvedo的博客 1647

Tire树(字典树)

1.1、什么是Trie树   Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。   Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。 它有3个基本性质: 根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应

qigaohua的博客 2317

疾病负担研究(GBD)——如何使用joinpoint软件计算AAPC

疾病负担研究(GBD)——如何使用joinpoint软件计算AAPC

weixin_44240228的博客 1万+

【图解算法】Trie树

Trie树,字符串查找树

就爱摆烂 5160

SQL注入绕过information_schema:实战技法与替代路径详解

SQL注入是Web安全领域的核心漏洞类型,其原理是通过构造恶意SQL语句,干扰应用程序与数据库的正常交互逻辑,从而窃取或篡改数据。在渗透测试与CTF竞赛中,绕过常见防护措施是提升技术能力的关键。当标准的信息收集方式受阻时,例如无法访问information_schema数据库,攻击者需要掌握替代的元数据获取方法。这些技术价值在于模拟真实环境中日益严密的防御体系,锻炼在受限条件下的系统性信息收集思维。典型的应用场景包括存在WAF过滤、权限限制或编码干扰的实战环境。本文将围绕SQL注入这一核心,深入探讨如何利用

weixin_33980459的博客 429

Docker离线部署OpenWebUI操作步骤

docker离线部署openwebui

m0_49333265的博客 4346

海量数据处理之Tire树(字典树)

参考博文:http://blog.youkuaiyun.com/v_july_v/article/details/6897097 第一部分、Trie树 1.1、什么是Trie树     Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较

田原的学习笔记 3万+

自动驾驶预测决策规划八股

预测规划八股个人总结。

dawushixiange的博客 479

Tire-Tree(前缀树,字典树)

在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。 Trie这个术语来自于retrieval。

yzf0011的专栏 4489

告别重打包:在Android 9上实现免Root的Frida-Gadget持久化Hook(附AOSP源码修改详解)

本文详细介绍了在Android 9上实现免Root的Frida-Gadget持久化Hook技术方案。通过修改AOSP源码,绕过传统重打包方式面临的签名校验和完整性检查,实现在非Root环境下的系统级Hook。文章包含核心代码修改、编译配置调整及调试技巧,为移动安全研究提供高效稳定的解决方案。

weixin_33726313的博客 501

Unreal5从入门到精通之Landscape地形系统

虚幻引擎 5 (UE5) 能够利用其强大的地形编辑工具套件创建大规模的地形世界。使用地形工具可以创建身临其境的户外地形,这些地形经过优化,可在多种不同设备上保持可播放的帧速率。

TxNet 4141

一种好用的树结构:Trie树

一种好用的树结构:Trie树

yanqianglifei的专栏 744

QT+Halcon实现螺纹检测

工业上要检测螺丝的内外直径、内外牙距、内外角度,现在比较好用的图像处理库,开源的opencv,收费的有halcon。为了实现螺纹检测,和对比螺纹检测拿个库比较好。分别用opencv和halcon实现了螺纹检测,通过对比发现用halcon实现的效果比较。现在用博客把实现过程记录下来: 1、需要检测的螺纹数据如下: 2、为了实现检测螺丝以上数据,螺纹内径、螺纹外径、螺纹外牙距、螺纹...

专注现代C++实战,从核心语法到高性能编程,助力开发者深入掌握系统级编程精髓。 7050

字典树与01字典树详解

【镇楼】 不满足于粗浅的表面了解字典树吗,今天!由我给大家带来!字典树与01字典树的解析!! 目录 【引入】 【字典树】 【01字典树】 【引用参考】 【引入】 字典是干啥的?查找字的。那么字典树顾名思义,自然也就是起查找作用的一种树,查找的是啥?单词。 我们先来看以下两个问题: 1、给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。 答:...

菜鸡成长史 4468

uniapp [全端兼容] - 实现连接蓝牙电子秤+监听数据转换并实时返回示例代码,uniApp实现BLE蓝牙连接多个电子秤设备、蓝牙通讯协议对接详细教程(全平台兼容H5、微信小程序、苹果安卓App)

uniapp连接蓝牙电子秤,uniapp如何连接电子秤蓝牙,蓝牙称重,实现监听数据转换并实时返回,多蓝牙,uni-app电子秤16进制蓝牙通讯协议对接,uniapp微信小程序蓝牙获取电子秤的值,uniapp蓝牙称重电子秤,蓝牙电子秤硬件,APP端连接蓝牙秤获取重量实时显示在页面上蓝牙秤,插件组件,蓝牙连接失败,uniapp安卓苹果ios连接蓝牙电子秤没反应,uniapp微信小程序 蓝牙低功耗连接发送数据监听接收,uni-app小程序蓝牙连接、读写数据全过程,uniapp连接蓝牙体脂秤,蓝牙搜索不到怎么办,如

🏆 前端领域优质创作者 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Trie 字典树 详解

一、字典树 1.字典树简介 字典树,英文名Trie,如其名:就是一棵像字典一样的树。 我们首先通过一张图来理解字典树的结构: 我们假定结点的顺序按照图中给定的顺序进行编号,容易发现,在一个给定的树上,从每个根节点出发到达子节点的路径边代表一个字母。实际上,每个节点出发的几条边所代表的字母是从左到右的顺序按照字典序排列的。 那么我们可以知道:从根节点出发,到达某个指定的结点的路径可以构成一个字...

HeartFireY的博客 6370

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

字典树,01字典树,可持续化01字典树(总结+例题)

目录 字典树 01字典树 字典树例题: power oj 2390: 查单词 HDU 1671 Phone List HDU 1004Let the Balloon Rise HDU 1075 What Are You Talking About HDU 4287 Intelligent IME HDU 1247 Hat’s W...

不二君 2601

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

字典树基础

字典树,是一种 空间换时间 的数据结构,又称Trie树、前缀树,是一种树形结构(字典树是一种数据结构),典型用于统计、排序、和保存大量字符串。所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的 字符串比较 ,查询效率比哈希树高。

weixin_45419660的博客 758

【C++】字典树

文章目录前言简介 前言 这是唯一一个我到现在写了的不能做A+B的数据结构,如能,还请神犇指教…… 想一想,百度的数据总量早已超过1TB=1024GB=1048576MB1TB=1024GB=1048576MB1TB=1024GB=1048576MB,是怎么为你迅速地查出来字典树的?当然是使用字典树。 简介 这是一棵字典树的图片: 在这个字典树中有两种点,红点和白点,后面都会解释。 这个字典树中...

__皮娃__的博客 1726

字典树简介

字典树(Trie)又名前缀树或单词查找树,最初是由美国计算机科学家 Edward Fredkin 在 1960 年提出。字典树是一种基于字符串序列的树形结构,可以高效地存储和检索字符串集合中的所有字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。字典树的优点是利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。字典树的核心思想是空间换时间,利用字符串的公共前缀减少查询时间以提高查询效率。

Doublelv 的博客专栏。 2214

字典树 与 01字典树

字典树可以降低空间复杂度;01字典树可以降低时间复杂度。 字典树:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 基本性质: 1、根节点不包含字符,出根节点外的每一个子节...

fanxingxue的博客 710

静态字典树和动态字典树模板

POJ 3630

小小码农 1675

字典树模版

九野的博客,转载请注明出处:http://blog.youkuaiyun.com/acmmmm/article/details/12250267 注意字典树的节点应该为 : 单词个数*单词长度 注意Trie结构体函数中的idx 字典树模版1: #define Word_Len 505000 #define Sigma_size 95 struct Trie{ ll ch[Word_Len][S

九野的博客 3013

字典树 01字典树【数据结构】

题目描述: 统计难题 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一...

tran_sient的博客 585
上一篇: 找出字符串中连续出现次数最多的子串
下一篇: 后缀树
crazyhacking
博客等级 码龄15年 299粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值