当前位置: 首页 > news >正文

Java / Scala - Trie 树简介与应用实现

目录

一.引言

二.Tire 树简介

1.树 Tree

2.二叉搜索树 Binary Search Tree

3.字典树 Trie Tree

3.1 基本概念

3.2 额外信息

3.3 结点实现

3.4 查找与存储

三.Trie 树应用

1.应用场景

2.Java / Scala 实现

2.1 Pom 依赖

2.2 关键词匹配

四.总结


一.引言

Trie 树即字典树,又称为单词查找树或键树,是一种树形结构,常用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计。

◆ 优点 - 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

◆ 思想 - 其核心思想是空间换时间,通过拆分字符串并存储换取查询的高效率

二.Tire 树简介

1.树 Tree

上面是最常见的树的形态,其拥有根节点 root,有左右的 sub-tree 子树,每个父结点 Parent Node 可能拥有子节点 Child Node,也有可能没有子节点,此时为 None。Siblings 代表同级的兄弟姐妹节点,Level 代表树的深度即层数。

2.二叉搜索树 Binary Search Tree

二叉搜索树(Binary Search Tree,简称 BST),又被称为二叉查找树、排序二叉树,是指一个空树或者具备下列性质的二叉树:

 若任意节点的左子树不为空,则左子树上所有节点的值都小于它的根节点的值。

 若任意节点的右子树不为空,则右子树上所有节点的值都大于它的根节点的值。  

 任意节点的左、右子树也分别为二叉搜索树。  

 没有键值相等的节点(即相同的元素只能出现一次)。

其具备以下特性:

◆ 中序遍历 - 对 BST 进行中序遍历会得到一个有序的序列。这是因为在中序遍历的过程中,先访问左子节点(较小),再访问当前节点,最后访问右子节点(较大)。

◆ 查找效率 - 在 BST 中查找一个元素的平均时间复杂度和树的深度有关,理想情况下,即 BST 是平衡的时候,时间复杂度是 O(log n),其中 n 是树中节点的数量。但是在最坏情况下,如树完全不平衡(退化成链表),查找时间复杂度退化为O(n)。

◆ 插入和删除操作 - 插入和删除也有可能改变树的结构。BST 的插入操作是指在满足上述性质的情况下,将一个新节点插入到树中。删除操作则可能涉及到重新调整树的结构,以保持二叉搜索树的性质。

3.字典树 Trie Tree

3.1 基本概念

注意这里 Trie 树不是二叉树,而是一颗多叉树,具体分多少叉要根据我们的实际场景来定。例如我们 Trie 树要存储所有英文单词,那理论上每一个父结点 Parent Node 要分 26 个子节点 Child Node,因为英文有 26 个英文字母。Trie 树具备如下基本性质:

结构本身不存储完整单词,而是存储每个细粒度的拆分项,例如单词搜索则存储字母

结从根结点到某一结点,将路径上的字符相连,为该结点对应的字符串

每个结点的所有子结点路径代表的字符都不相同,这里其实代表没有重复字符串结点

3.2 额外信息

每个 Node 结点除了存储对应的字符外,其还可以具备其自己的属性,最简单的,上面的示例中给出了对应字符串的出现频次,这可以作为搜索推荐的参考依据,如果是代码,其额外信息可以作为一个 Class 存在,内部包含该节点多个属性,例如字符串对应的领域、频率、长度、适用范围等等。 说到词频,也让我们想起来 Word2vec 里用到的霍夫曼树,其在构造编码时也考虑了词频的因素,使得词频高的词可以尽可能快的找到。

3.3 结点实现

这里对于每个 Node 而言,结点就不存在 Left 和 Right 的概念了,而是直接对应下一个可能的字符串,选定哪个字符串,就到下一个字符串对应的 Node 上。如果我们认为是简单单词且不区分大小写,我们可以认为每个 Node 最多有 26 个分叉结点,但如果有更多字符或特殊符号的加入,那么多叉树会有更多的分叉。如果一个结点指向 null 代表其没有儿子结点,此时连接其路径上的字符即可得到该结点对应的字符串表示。

3.4 查找与存储

◆ 存储

假设是上面提到的英文单词查找,且不区分大小写,此时最坏的情况为 26 叉树,每分叉一次,一个结点就多 26 个叉,这样的指数分叉对于存储空间还是有很大的消耗。

◆ 查找

相比于存储的消耗,查找的速度会快很多,因为查找的次数是和单词的字符量匹配的,常见的英文单词字符量在 10 左右,那我们只需要 10 次的常数时间就可以查到,以 you 为例,只需要 3 步就可以找到。但如果是用二分查找等方法,由于整个字典集的数量 n 特别大,即使排好序也是 Log(n) 的查找效率,会比 Trie 树查找次数多很多。这也体现了我们开头说的 Trie 树的核心思想: 空间换时间。其实这个概念不光是 Trie 树,很多算法都会用到这个思想,将时间复杂度降低,空见复杂度提升。

三.Trie 树应用

1.应用场景

因为 Trie 树公共前缀的使用, 所以它十分适合搜索与输入法拓展等领域,当我们输入了前面的公共前缀,其可以根据词频很容易的给出后面的候选。 实际场景中应用较多的是 Aho-Corasick 算法,其适用于确定性的、完全匹配的字符串搜索场景,它能够高效地检测出预定义的关键词是否在给定文本中出现。针对每一次输入,算法都能找出所有存在的关键词匹配。

2.Java / Scala 实现

2.1 Pom 依赖

        <!-- https://mvnrepository.com/artifact/org.ahocorasick/ahocorasick --><dependency><groupId>org.ahocorasick</groupId><artifactId>ahocorasick</artifactId><version>0.6.3</version></dependency>

2.2 关键词匹配

import org.ahocorasick.trie.{Emit, Token, Trie}// 初始化并构建Trieval trie = Trie.builder().addKeyword("hers").addKeyword("his").addKeyword("she").addKeyword("he").build()// 搜索文本val text = "she sells sea shells by the sea shore"// 执行搜索val tokens: java.util.Collection[Token] = trie.tokenize(text)// 注意这里使用Java转Scala的集合转换import scala.collection.JavaConverters._for (token <- tokens.asScala) {if (token.isMatch) {// 打印匹配的词条和位置println(s"Found match: ${token.getFragment} at position ${token.getEmit.getStart}")}}

- addKeyword 用于添加关键词到 Trie 树中

- text 为代分析的文本

- tokenize 方法分析文本进行关键词匹配

- isMatch getFragment 获取命中的关键词,getEmit.getStart 与 getEnd 用于获取 Fragment 片段在 text 中的起始位置

实战场景下,Builder 过程中会添加一个很大的字典内容构造 Trie 树,随后应用 Trie 树进行文本的关键词匹配,判断目标文本是否命中字典中给定的关键字。

四.总结

上面就是 Trie 树的简单介绍与应用。如果想要开发类似 Google 的关键词搜索推荐系统要比使用简单的 Aho-Corasick 算法要复杂得多,并且可能需要依赖机器学习和大数据处理技术。 如果你只是想实现一个简单版本的搜索推荐系统,可以考虑一些基础的模糊匹配算法或使用现有的搜索引擎库,比如 Elasticsearch,它内置了自动补全和模糊匹配的功能,同时 Elasticsearch 也能够通过集群分布式架构来处理大规模数据集,非常适用于构建搜索推荐系统。

相关文章:

Java / Scala - Trie 树简介与应用实现

目录 一.引言 二.Tire 树简介 1.树 Tree 2.二叉搜索树 Binary Search Tree 3.字典树 Trie Tree 3.1 基本概念 3.2 额外信息 3.3 结点实现 3.4 查找与存储 三.Trie 树应用 1.应用场景 2.Java / Scala 实现 2.1 Pom 依赖 2.2 关键词匹配 四.总结 一.引言 Trie 树…...

JS/jQuery 获取 HTTPRequest 请求标头?

场景&#xff1a;在jquery封装的ajax请求中&#xff0c;默认是异步请求。 需要定一个秘钥进行解密&#xff0c;所以只能存放在请求头中。然后需要值的时候去请求头中读取。 注意&#xff1a;dataType设置&#xff0c;根据请求参数的格式设置&#xff0c;如果是加密字符串&…...

Leetcode—2034.股票价格波动【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—2034.股票价格波动 算法思想 实现代码 class StockPrice { public:int last 0;multiset<int> total;unordered_map<int, int> m;StockPrice() {}void update(int timestamp, int price) {if(m.count(time…...

【Linux】diff命令使用

diff命令 是一个用于比较两个文件或目录之间差异的命令。它可以显示两个文件之间的行级别差异&#xff0c;并以易于阅读的格式输出结果。 著者 由保罗艾格特、迈克海特尔、大卫海耶斯、理查德史泰尔曼和Len Tower撰写。 diff命令 -Linux手册页 语法 diff [选项] [文件1]…...

讯飞星火认知大模型与软件测试结合,提升软件质量与效率

随着人工智能技术的不断发展&#xff0c;越来越多的企业开始将其应用于软件开发过程中。其中&#xff0c;讯飞星火认知大模型作为一种基于深度学习的自然语言处理技术&#xff0c;已经在语音识别、机器翻译、智能问答等领域取得了显著的成果。而在软件测试领域&#xff0c;讯飞…...

【Flink on k8s】- 4 - 在 Kubernetes 上运行容器

目录 1、准备 k8s 集群环境、Docker 环境 2、启用 kubernetes 2.1 查询 k8s 集群基本状态...

软件重装或系统重装后避免重复踩坑

1. Office软件的坑在于字体又没了 Word字体库默认没有仿宋_GB2312和楷体仿宋_GB2312&#xff0c;需要手动添加。 提供如下两个下载链接&#xff0c;亲测有效&#xff1a; 仿宋_GB2312 楷体_GB2312 安装步骤&#xff1a;解压-复制.ttf文件至C:\Windows\Fonts 持续更新贴~...

【Jmeter】JSON Extractor变量包含转义字符,使用Beanshell脚本来消除

如果使用Jmeter的JSON Extractor提取的变量包含特殊字符&#xff0c;直接引用时会包含转义字符。可以使用Beanshell脚本来进行字符串转换&#xff0c;从而消除这些转义字符。 import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONArray; import com.ali…...

GO设计模式——5、建造者模式(创建型)

目录 建造者模式&#xff08;Builder Pattern&#xff09; 建造者模式的核心角色 优缺点 使用场景 注意事项 代码实现 建造者模式&#xff08;Builder Pattern&#xff09; 建造者模式&#xff08;Builder Pattern&#xff09;是将一个复杂对象的构建与它的表示分离&…...

《LeetCode力扣练习》代码随想录——字符串(反转字符串II---Java)

《LeetCode力扣练习》代码随想录——字符串&#xff08;反转字符串II—Java&#xff09; 刷题思路来源于 代码随想录 541. 反转字符串 II 模拟过程 class Solution {public String reverseStr(String s, int k) {if(s.length()1){return s;}char[] chs.toCharArray();for(int i…...

WMMSE方法的使用笔记

标题很帅 原论文的描述WMMSE的简单应用 无线蜂窝通信系统的预编码设计问题中&#xff0c;经常提到用WMMSE方法设计多用户和速率最大化的预编码&#xff0c;其中最为关键的一步是将原和速率最大化问题转化为均方误差最小化问题&#xff0c;从而将问题由非凸变为关于三个新变量的…...

MySQL核心知识点整理大全1-笔记

目录 MySQL 一、MySQL的基本概念 1.数据库 2.表 3.列 4.行 5.主键 6.索引 二、MySQL的安装与配置 1.下载MySQL安装包 2.安装MySQL 3.启动MySQL 4.配置MySQL a.设置监听端口和IP地址 b.设置数据存储路径 c.设置字符集和排序规则 5.测试MySQL 三、MySQL的基本操…...

理解输出电压纹波和噪声:来源与抑制

医疗设备、测试测量仪器等很多应用对电源的纹波和噪声极其敏感。理解输出电压纹波和噪声的产生机制以及测量技术是优化改进电路性能的基础。 1&#xff1a;输出电压纹波 以Buck电路为例&#xff0c;由于寄生参数的影响&#xff0c;实际Buck电路的输出电压并非是稳定干净的直流…...

uni-app 微信小程序之好看的ui登录页面(二)

文章目录 1. 页面效果2. 页面样式代码 更多登录ui页面 uni-app 微信小程序之好看的ui登录页面&#xff08;一&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;二&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;三&#xff09; uni-app 微信小程…...

Textual Inversion

参考博客1:https://www.bilibili.com/read/cv25430752/...

笙默考试管理系统-MyExamTest----codemirror(47)

笙默考试管理系统-MyExamTest----codemirror&#xff08;44&#xff09; 目录 笙默考试管理系统-MyExamTest----codemirror&#xff08;44&#xff09; 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试…...

JVM中 Minor GC 和 Full GC 的区别

Java中的垃圾回收&#xff08;Garbage Collection, GC&#xff09;是自动内存管理的一部分&#xff0c;其主要职责是识别并清除程序中不再使用的对象来释放内存。Java虚拟机&#xff08;JVM&#xff09;在运行时进行垃圾回收&#xff0c;主要分为两种类型&#xff1a;Minor GC和…...

二十一章(网络通信)

计算机网络实现了多台计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互之间可以交换数据。编写网络应用程序前&#xff0c;首先必须明确所要使用的网络协议…...

[linux运维] 利用zabbix监控linux高危命令并发送告警(基于Zabbix 6)

之前写过一篇是基于zabbix 5.4的实现文章&#xff0c;但是不太详细&#xff0c;最近已经有两个小伙伴在zabbix 6上操作&#xff0c;发现触发器没有str函数&#xff0c;所以更新一下本文&#xff0c;基于zabbix 6 0x01 来看看效果 高危指令出发问题告警&#xff1a; 发出邮件告…...

手机升级到iOS15.8后无法在xcode(14.2)上真机调试

之前手机是iOS14.2的系统,在xcode上进行真机测试运行良好&#xff0c;因为想要使用Xcode的Instruments功能&#xff0c;今天将系统更新到了iOS15.8 &#xff0c;结果崩了 说是Xcode和手机系统不兼容不能进行真机测试。在网上查了好些方法&#xff0c;靠谱的就是下载相关版本的…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...