探索AC自动机:多关键词搜索的原理与应用案例

news/2024/9/20 12:08:08/文章来源:https://www.cnblogs.com/Jcloud/p/18381168

引言

目前,大多数自由文本搜索技术采用类似于Lucene的策略,通过解析搜索文本为各个组成部分来定位关键词。这种方法在处理少量关键词时表现良好。但当搜索的关键词数量达到10万个或更多时,这种方法的效率会显著下降,尤其是在需要与词典进行详尽对比的场景中。本文将介绍的Aho-Corasick(AC)自动机作为多模式匹配中的经典算法,不仅能够处理大规模文本数据,还能确保搜索过程的实时性和准确性。

AC自动机:文本搜索的革命性工具

AC自动机可以被形象地比喻为一个超级找词机器。想象你手头有一本内容繁多的书籍和一份包含多个词语的列表,你的任务是快速找出所有这些词语在书中出现的位置。如果采用传统方法,即逐个词进行查找,工作量将会非常巨大。而AC自动机通过构建一种特殊的树状结构——前缀树或Trie,来极大地提升搜索效率。

AC自动机构建与搜索机制

构建前缀树(Trie)

AC自动机首先会根据所有关键词构建一个前缀树。这种树状结构的每个节点代表一个字母,并且每个字母都指向下一个可能的字母,从而形成一个连续的路径,表示一个或多个关键词的前缀

 


 

图片来源网络

失配指针(Fail指针)

在搜索过程中,如果当前路径上无法找到匹配的关键词,AC自动机会利用失配指针进行快速回溯。这些指针预先设置在树的每个节点上,指向其他可能的匹配路径,从而避免了从头开始搜索的低效性

 


 

图片来源网络

实时搜索与高效报告

AC自动机在读取文本的同时,能够快速地遍历前缀树结构。一旦发现关键词出现在文本中,它能够立即报告这个词及其出现的位置。这种能力使得AC自动机能够一次性高效完成大量关键词的搜索任务

 


 

图片来源网络

算法核心组件与复杂度

核心组件:

goto(转跳):每个遇到的字符都会被提交给goto结构中的状态对象,以确定新的当前状态
fail(失败转移):如果没有找到匹配状态,算法会触发fail并回溯至深度更浅的状态,从那里继续搜索
output(输出):每当达到与整个关键词相匹配的状态时,该状态会被发送到输出集合中,完成扫描后即可读取这些匹配项

时间复杂度:

Aho-Corasick算法的时间复杂度为O(n),其中n是文本的长度。这意味着无论提供多少关键词,搜索的性能都将呈线性下降,与关键词的数量无关。

AC自动机的应用

AC自动机在多种场景下都能发挥重要作用,包括:

在文本中查找并链接或突出显示关键词,提高信息的可检索性
为纯文本添加语义,使文本内容更加丰富和有层次
检查文本中的语法错误,通过与词典的对比来识别和纠正错误

应用案例:使用Aho-Corasick算法来识别和高亮HTML文本中的关键词

本Java程序将演示如何使用Aho-Corasick自动机库来搜索和高亮HTML文本中的关键词。程序首先构建一个自动状态机,该状态机被训练识别一系列中文关键词。然后,程序将处理HTML文档,查找这些关键词的出现,并用<b>标签将它们包裹起来,以实现加粗显示的效果。

第一步:Maven依赖配置,引入Aho-Corasick自动机库

<dependency><groupId>org.ahocorasick</groupId><artifactId>ahocorasick</artifactId><version>0.6.3</version>
</dependency>

第二步:代码实现

public class HighlightKeywordsInHtml {public static void main(String[] args) {// 定义HTML内容的字符串,包含了南京大学的介绍String htmlContent = createHtmlContentForNanjingUniversity();// 创建Aho-Corasick Trie的构建器实例Trie trie = buildAhoCorasickTrie();// 使用Trie实例处理HTML文本,获取匹配的Token集合Collection<Token> tokens = trie.tokenize(htmlContent);// 使用StringBuilder构建最终的HTML字符串,用于输出高亮的关键词StringBuilder html = new StringBuilder();html.append("<html><body><p>");// 遍历Token集合for (Token token : tokens) {// 如果Token匹配关键词,则添加<b>标签以实现加粗效果if (token.isMatch()) {html.append("<b>");}// 添加Token对应的文本片段html.append(token.getFragment());// 如果Token匹配关键词,结束<b>标签if (token.isMatch()) {html.append("</b>");}}// 完成HTML字符串的构建html.append("</p></body></html>");// 打印最终的HTML字符串,其中包含高亮显示的关键词System.out.println(html);}private static String createHtmlContentForNanjingUniversity() {// 此处添加创建南京大学HTML内容的方法实现String speech = """<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>南京大学简介</title><style>body {font-family: "微软雅黑", "宋体", Arial, sans-serif;line-height: 1.6;color: #333;}.university-intro {text-align: justify;margin-bottom: 2em;padding: 1rem;background-color: #f5f5f5;border-radius: 5px;}</style></head><body><section class="university-intro"><h1>南京大学:百年名校,学术卓越</h1><p>南京大学,简称“南大”,位于中国江苏省南京市,是中国最顶尖的高等学府之一,拥有百年的办学历史和深厚的文化底蕴。作为中国教育部直属的全国重点大学,南大以其卓越的学术成就和教育质量闻名于世。</p><p>南京大学以其强大的师资力量和学术研究而著称,提供多元化的学科教育,包括自然科学、人文社会科学、工程技术等多个领域。学校注重培养学生的创新能力和国际视野,为国家和社会培养了大量杰出人才。</p><p>南大校园环境优美,历史与现代交融,是学术研究和知识探索的理想场所。学校在计算机科学、地球科学、化学等学科领域具有国际领先水平,并在推动科学技术进步和文化传承方面发挥着重要作用。</p></section></body></html>""";return speech;}private static Trie buildAhoCorasickTrie() {return Trie.builder().ignoreOverlaps() // 设置不捕获重叠的关键词.onlyWholeWords() // 仅匹配完整的单词.ignoreCase() // 忽略关键词的大小写.addKeywords(Arrays.asList("南京大学", "南大", "地球科学")).build(); // 构建Trie实例}
}

第三步:运行程序,符合预期

<html><body><p><!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>南京大学简介</title><style>body {font-family: "微软雅黑", "宋体", Arial, sans-serif;line-height: 1.6;color: #333;}.university-intro {text-align: justify;margin-bottom: 2em;padding: 1rem;background-color: #f5f5f5;border-radius: 5px;}</style>
</head>
<body>
<section class="university-intro"><h1><b>南京大学</b>:百年名校,学术卓越</h1><p><b>南京大学</b>,简称“<b>南大</b>”,位于中国江苏省南京市,是中国最顶尖的高等学府之一,拥有百年的办学历史和深厚的文化底蕴。作为中国教育部直属的全国重点大学,南大以其卓越的学术成就和教育质量闻名于世。</p><p>南京大学以其强大的师资力量和学术研究而著称,提供多元化的学科教育,包括自然科学、人文社会科学、工程技术等多个领域。学校注重培养学生的创新能力和国际视野,为国家和社会培养了大量杰出人才。</p><p>南大校园环境优美,历史与现代交融,是学术研究和知识探索的理想场所。学校在计算机科学、<b>地球科学</b>、化学等学科领域具有国际领先水平,并在推动科学技术进步和文化传承方面发挥着重要作用。</p>
</section>
</body>
</html>
</p></body></html>

本文对Aho-Corasick(AC)自动机算法进行了抛砖引玉,揭示了其在处理大规模文本数据方面的卓越性能和应用潜力。若你渴望深入挖掘AC算法的精髓,进一步探索其高级应用和实现细节,建议参考以下的参考资料进行进一步的学习与挖掘。

参考资料

1. http://cr.yp.to/bib/1975/aho.pdf

2. https://github.com/robert-bor/aho-corasick

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/787579.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VL21 根据状态转移表实现时序电路

根据给的状态转移表知道有两个状态:第一列的为current_state,第二三列为next_state,且仅当current_state==11时候Y为1(使用()?:语法实现)。三段式状态机的流程: 第一段:时序逻辑,公式化写法 第二段:组合逻辑,这里要注意always @(*)是固定写法,不能像第一段写成时…

Vue3.5新增的baseWatch让watch函数和Vue组件彻底分手

Vue3.5新增了一个baseWatch,让watch函数和Vue组件彻底分手,他的实现和Vue组件以及生命周期没有一毛钱关系。前言 在Vue 3.5.0-beta.3版本中新增了一个base watch函数,这个函数用法和我们熟知的watch API一模一样。区别就是我们之前用的watch API是和Vue组件以及生命周期是一…

硬件设备snmp配置,snmp如何检测联通信

【1】山石网科防火墙 环境需求:设备与 prometheus 服务器之间需要放通UDP161端口,且网络能连通配置路径:系统——SNMP 1、配置SNMP代理 勾选‘启用’选项,并点击 应用 即可 2、配置SNMP主机 点击‘新建’,添加 zabbix服务器IP地址跟团体名,权限为 只读,点击 确定 完成新…

mmdetection中的dataset pipline

参考: 轻松掌握 MMDetection 整体构建流程(二) 商汤开源目标检测工具箱mmdetection代码详解(三)----------mmdetection数据的输入、处理过程 1. mmdetection中的数据加载流程 pipline中由一系列数据处理模块对数据集进行流水线般的处理要注意的是,上述pipline流程在3.x版本…

南沙信奥赛陈老师讲题:1331:【例1-2】后缀表达式的值

1331:【例1-2】后缀表达式的值 时间限制: 10 ms 内存限制: 65536 KB提交数:65784 通过数: 17299 【题目描述】从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘(*)、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要…

windows解决0x80070035找不到网络路径的问题

windows进行网络共享,无法访问,报错0x80070035,找了好几个办法都没有用.无意间尝试开启有密码保护的共享后,成功解决问题. 搜索高级共享->管理高级共享设置->密码保护的共享->勾选有密码保护的共享

使用nginx代理,简单实现一个静态网页功能(扫描二维码)

1、创建项目目录 mkdir my-image-page cd my-image-page2、准备图片和HTML文件上传图片:将 image.jpg 上传到 my-image-page 目录。创建HTML文件:在同一目录下创建一个 index.html 文件<!DOCTYPE html> <html lang="en"> <head><meta charset…

P2757 [国家集训队] 等差子序列 和 CF452F Permutation

讲解 P2757 [国家集训队] 等差子序列 和 CF452F Permutation。考虑枚举中间数,将问题转化为区间判定是否回文,使用线段树与哈希算法解决。题意: 给定一个长度为 \(n\) 的排列 \(a\),判断其中是否有长度 \(\ge 3\) 的等差数列。 \(1 \le n \le 5 \times 10^5\)。 思路: 首…

C# 获取PDF页面大小、方向、旋转角度

在处理PDF文件时,了解页面的大小、方向和旋转角度等信息对于PDF的显示、打印和布局设计至关重要。本文将介绍如何使用免费.NET 库通过C#来读取PDF页面的这些属性。C# 读取PDF页面大小(宽度、高度) C# 判断PDF页面方向 C# 检测PDF页面旋转角度免费库 Free Spire.PDF for .NET…

uni-app小程序(快手、抖音)getCurrentPages使用坑位记录

前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验也挺棒的,公司项目就是主推uni-app。 坑位 最近在做一个需求,在达到一定条件的情况下我需要根据路由堆栈中是否有我指定的页面来做不同的跳转,如果路由…

WPF 路由事件2

1什么是路由事件 简单说,路由事件可以沿着视觉树VisualTree进行传递,在这视觉树中的所有对象都可以收到这个事件。前提是添加了检测。 1.1什么是逻辑树LogicalTree 简单理解:逻辑树就是我们在xaml中写的布局逻辑 如xaml代码:<Grid><StackPanel Orientation="…

算法与数据结构——栈

栈 栈(stack)是一种遵循先入后出逻辑的线性数据结构。如图所示,我们将堆叠元素的顶部称为“栈顶”,底部称为“栈底”。将吧元素添加到栈顶的操作叫做“入栈”,删除栈顶的操作叫做“出栈”。 栈的常用操作方法 描述 时间复杂度push() 元素入栈(添加至栈顶) O(1)pop() 栈顶…