关于 AC 自动机

什么是 AC 自动机

AC 自动机,全称 Aho-Corasick 自动机,是一种用于字符串搜索的算法,由 Alfred V. Aho 和 Margaret J. Corasick 在 1975 年提出。这个算法是为了解决在一个主文本字符串中查找多个模式字符串(或称为“关键词”)的问题,它可以在线性时间内完成搜索,非常高效。

下文是 wiki 百科中的原文内容

在计算机科学中,Aho-Corasick 算法是 Alfred V. Aho 和 Margaret J. Corasick 于 1975 年发明的一种字符串搜索算法。 [1]它是一种字典匹配算法,用于在输入文本中定位有限字符串集(“字典”)的元素。它同时匹配所有字符串。算法的复杂度与字符串的长度加上搜索文本的长度加上输出匹配的数量呈线性关系。请注意,由于找到了所有匹配项,因此如果每个子字符串都匹配,则匹配项的数量可能是二次方(例如,dictionary = a、aa、aaa、aaaa 和 input 字符串是aaaa)。

通俗地说,该算法构建了一个类似于特里树的有限状态机,在各个内部节点之间具有附加链接。这些额外的内部链接允许在失败的字符串匹配之间快速转换(例如,在不包含 cart 的 trie 中搜索 cart,但包含 art,因此会在以 car 为前缀的节点处失败)到共享的 trie 的其他分支通用后缀(例如,在前面的情况下,属性分支可能是最好的横向转换)。这允许自动机在字符串匹配之间转换,而不需要回溯。

当预先知道字符串字典(例如计算机病毒数据库)时,可以离线执行自动机的构造,并将编译后的自动机存储起来供以后使用。在这种情况下,其运行时间与输入长度加上匹配条目的数量成线性关系。Aho-Corasick 字符串匹配算法构成了原始 Unix 命令 fgrep 的基础。

In computer science, the Aho—Corasick algorithm is a string-searching
algorithm invented by Alfred V. Aho and Margaret J. Corasick in
1975.[1] It is a kind of dictionary-matching algorithm that locates elements of a finite set of strings (the “dictionary”) within an input
text. It matches all strings simultaneously. The complexity of the
algorithm is linear in the length of the strings plus the length of
the searched text plus the number of output matches. Note that because all matches are found, there can be a quadratic number of matches if every substring matches (e.g. dictionary = a, aa, aaa, aaaa and input string is aaaa).

Informally, the algorithm constructs a finite-state machine that
resembles a trie with additional links between the various internal
nodes. These extra internal links allow fast transitions between
failed string matches (e.g. a search for cart in a trie that does not
contain cart, but contains art, and thus would fail at the node
prefixed by car), to other branches of the trie that share a common
suffix (e.g., in the previous case, a branch for attribute might be
the best lateral transition). This allows the automaton to transition
between string matches without the need for backtracking.

When the string dictionary is known in advance (e.g. a computer virus
database), the construction of the automaton can be performed once
off-line and the compiled automaton stored for later use. In this
case, its run time is linear in the length of the input plus the
number of matched entries.

The Aho—Corasick string-matching algorithm formed the basis of the
original Unix command fgrep.

如何被想出来的呢?

Aho 和 Corasick 设计这个算法的初衷是为了提高字符串匹配的效率,特别是在需要同时查找多个模式字符串时。当时的背景是计算机科学正在迅速发展,人们需要更高效的算法来处理大量的文本数据。AC 自动机的设计灵感部分来自于有限状态机(Finite State Machine, FSM)和 Trie(字典树)的概念,通过将多个模式字符串构建成一个具有状态转移功能的 Trie 树,并在此基础上添加失败指针(fail pointer),使得在匹配失败时能够高效地转移到下一个可能的状态,从而避免了重复的匹配工作。

适用的场景

AC 自动机的主要应用场景包括:

  • 文本过滤和内容审查: AC 自动机可以用来在文本中查找敏感词或特定的词组,因此在内容审查和敏感信息过滤的系统中非常实用。
  • 生物信息学: 在基因序列分析中,可能需要在 DNA 序列中查找多个短序列,AC 自动机因其高效性而被广泛应用。
  • 网络安全: 在网络入侵检测系统(IDS)中,AC 自动机可用于匹配多种入侵签名或恶意代码片段。
  • 文本挖掘和自然语言处理: 在大规模文本数据中查找多个关键词或短语时,AC 自动机可以提供高效的解决方案。
  • 编译原理: 在词法分析阶段,AC 自动机可用于高效识别多个关键字和模式字符串。

原理之前的扩展

何为 Trie 树

Trie树(发音为"try"),又称为前缀树或字典树,是一种树形结构,它是一种用于快速检索字符串数据集中特定字符串的高效数据结构。

Trie树的基本概念和特点:

节点结构:Trie树的每个节点通常包含多个子节点,每个子节点代表一个字符。从根节点到某一节点的路径,代表一串字符。

  • 前缀共享:在Trie树中,具有共同前缀的字符串会共享前缀的路径。例如,字符串"tree"和"trie"会在前两个字符"tr"后分叉成两条路径。
  • 结束标记:为了标识一个字符串完整地出现在Trie树中,会在字符串的最后一个字符对应的节点上做一个特殊标记,如设置一个布尔标记或存储一个指向数据的引用。
  • 快速查找:使用Trie树可以在O(m)时间内查找一个长度为m的字符串,这是因为它几乎不涉及字符串比较操作。

Trie树的构建过程:

初始化: 从一个根节点开始,根节点通常不包含字符。
插入字符串: 将每个字符串的字符逐个插入到Trie树中。如果某个字符对应的节点不存在,则创建它。
重复字符: 如果插入的字符在Trie树中已有对应的节点,则沿着该节点继续插入下一个字符。
结束标记: 每个字符串的末尾字符对应的节点被标记为结束节点,表明一个字符串已经插入完成。

Trie树的应用场景:

词频统计:统计大量文本中单词的出现次数。
自动补全:搜索引擎中的自动补全功能。
拼写检查:检查单词的拼写是否正确。
字符串检索:在一组字符串中快速检索出包含特定前缀的所有字符串。

Trie树由于其高效的查找性能,特别适合于处理字符串匹配相关的问题。

何为自动机

“自动机”(Automaton)在计算机科学中通常指的是一种抽象的机器,它能够根据输入自动执行一系列操作,而不需要外部的干预。自动机通常根据一组规则或算法自动处理输入序列,并根据这些输入改变其内部状态,可能还会生成输出。它们在形式语言理论、编译器设计、文本处理等领域中有着广泛的应用。

Aho-Corasick自动机是一种特定类型的自动机,它根据一组预定义的字符串(模式)进行构建,当文本输入流被送入自动机进行处理时,AC自动机会自动地匹配这些预定义的模式。它之所以被称为自动机,是因为它能自动完成以下操作:

状态转换: AC自动机有一系列内部状态,这些状态对应于Trie树中的节点。每读取输入文本中的一个字符,自动机就根据当前状态和输入字符转移到下一个状态。

模式识别: 当输入文本中的某个部分与某个预定义的模式匹配时,AC自动机会识别出这个匹配,并可以执行相关的动作(例如,返回匹配位置、记录匹配等)。

失败转移: 如果当前状态没有一个直接的转移对应于当前的输入字符,自动机会使用失败指针(fail pointer)来找到下一个可能的状态,而不是从头开始匹配。

输出结果: 每当AC自动机到达某个状态,它会检查该状态是否对应于某个(或某些)预定义模式的结束。如果是,自动机将输出与当前状态相对应的模式的匹配信息。这些信息可能包括模式的起始索引、结束索引或是已匹配的文本部分。

因此,"自动机"这个名词强调了AC自动机在不需要人工干预的情况下对模式进行高效匹配的能力。自动机在遇到失败匹配时不需要回溯输入文本,而是能够利用内部的失败指针自动地跳转到其他可能的匹配状态,这是它与简单的模式匹配算法相比的一个显著优势。这种自动的状态转移和匹配检测过程是它得名"自动机"的原因。

Trie 树与 AC 自动机的联系

Trie 树,又称前缀树或字典树,是一种用于快速检索字符串数据集中的键的有序树结构。这种数据结构允许共享前缀,可以非常高效地存储和检索字符串集合中的关键字。Trie 树的每个节点代表一个字符串(或者字符串的一部分),每条边代表一个字符。从根节点到某一节点的路径对应于字典中的一个单词或者单词的前缀。

对于 Aho-Corasick 自动机,它确实是基于 Trie 树的,并在其上添加了失败指针来实现快速的模式匹配。如果你需要向 AC 自动机中添加新的元素,确实可能需要对树进行一定的更新或重建,尤其是更新失败指针。在实际应用中,如果频繁地添加新元素,这种重建可能会变得耗时。

AC 自动机本身就是一种特殊的数据结构,它结合了 Trie 树和状态机的特点。如果你要谈论这种结构并强调其用于模式匹配的特性,通常就会称之为 Aho-Corasick 自动机,简称 AC 自动机。在文献中,它没有一个不同的专用名称,通常就是直接称为 Aho-Corasick 自动机或者 AC 自动机。

在某些实现中,为了避免重建整个数据结构,可能会采用更灵活的数据结构,或者在 AC 自动机的基础上进行改进,使其支持动态插入和删除操作,但这通常会增加实现的复杂性。在需要处理动态变化的模式集合时,这些改进可能会提供更好的性能。

AC 自动机的原理

AC 自动机(Aho-Corasick 算法)是一种用于在输入文本中快速查找多个模式(即字符串)出现的算法。它由 Alfred V. Aho 和 Margaret J. Corasick 在 1975 年提出,主要用于字符串匹配问题,特别是在处理大量模式匹配时非常有效。AC 自动机的核心思想是将所有模式构建成一个有限状态机(Trie 树结构),并在这个结构中加入失败指针(fail pointer),使得在匹配失败时能快速转移到下一个可能的状态,从而避免重复检查之前已经匹配过的文本。

AC 自动机的构建过程

构建 AC 自动机的过程主要分为两个步骤:构建 Trie 树添加失败指针

构建 Trie 树:

  • 首先,将所有模式串构建成 Trie 树。每个节点代表一个字符,从根节点到某一节点的路径代表一个模式串的前缀。
  • 每个模式串的终点节点标记为输出,表示该路径对应的模式串已完全匹配。

添加失败指针:

  • 对于 Trie 树的根节点的所有直接子节点,它们的失败指针都指向根节点。
  • 对于其他节点,假设当前节点标记为字符 C,其父节点的失败指针指向的节点有一个直接子节点也标记为字符 C,则当前节点的失败指针指向那个子节点。如果找不到,就递归地沿着失败指针继续查找,直到到达根节点。

工作原理

在文本匹配阶段,AC 自动机从根节点开始,按照文本字符逐个进行转移,如果遇到匹配失败的情况,就通过失败指针跳转到其他分支继续匹配,这样可以避免从头开始匹配,提高效率。当到达某个节点时,如果该节点是输出节点,或者沿着失败指针可以回溯到一个输出节点,那么就找到了一个模式串的匹配。

用例举例

假设我们有一段文本 “abccab”,我们需要在这段文本中查找以下模式串:“a”, “ab”, “bc”, “bca”, “c” 和 “caa”。

构建 Trie 树: 首先基于这些模式串构建 Trie 树。
添加失败指针: 然后为 Trie 树中的每个节点添加失败指针。
文本匹配: 最后,使用 Trie 树来匹配整段文本。

在这个例子中,每个节点除了有指向子节点的指针外,还有一个失败指针(用虚线表示)。例如,节点 “b” 的失败指针指向根节点,因为当在 “ab” 后面遇到非 “c” 的字符时,下一个可能的匹配是从头开始的 “a”。

通过这种方式,AC 自动机可以在 O(n) 的时间复杂度内完成对所有模式串的匹配,其中 n 是文本的长度。这使得 AC 自动机在诸如网络内容过滤、生物信息学序列分析、文本编辑器的查找替换等场景中非常有用。

视频解释

可以结合上文的文字描述加上简单直观的视频解释,就可以很轻松的弄明白 AC 自动机的原理了。
用最直观的方式解释 AC 自动机

实际用例举例

此图是维基百科中举例的图片。我们对此张图片涉及到的构建、添加失败指针、文本匹配来一一做对应的解释。
在这里插入图片描述
构建Trie树(黑色"子节点"弧线):

从根节点开始,为字典中的每个单词构建一条路径。这些黑色弧线代表从一个节点通过添加一个字符到达另一个节点的转移。例如,从根节点到节点"a",然后到节点"ab",这样为单词"ab"在Trie树中建立一条路径。
如果一个节点代表字典中的一个完整单词,那么这个节点是白色的。如果它不代表一个完整的单词,只是单词的一个前缀,那么它是灰色的。

添加失败指针(蓝色"后缀"弧线):

对于图中的每个节点,都有一个指向它的最长可能严格后缀的节点的蓝色弧线。“严格后缀"意味着除了节点本身之外的后缀。例如,对于节点"caa”,它的严格后缀是"aa"、“a"以及根节点(空字符串),而图中存在的最长后缀是"a”,因此有一条从"caa"到"a"的蓝色弧线。

这些蓝色弧线能够通过广度优先搜索计算得出,当访问到一个节点时,可以通过跟随其父节点的蓝色弧线来找到它的最长后缀节点,并检查该后缀节点的子节点中是否有与当前节点匹配的字符。如果没有匹配,则继续跟随蓝色弧线寻找下一个最长后缀,直到找到匹配或到达根节点。

添加绿色"字典后缀"弧线:

绿色弧线从每个节点出发,直接指向通过蓝色弧线能够到达的下一个字典中的单词节点。例如,从节点"bca"出发,跟随蓝色弧线可以先到"ca",再到"a",而"a"是字典中的一个单词,所以从"bca"到"a"有一条绿色的弧线。

这些绿色弧线可以通过从每个节点出发,沿着蓝色弧线重复遍历,直到找到一个代表字典中单词的节点(蓝色节点)计算得出,并且可以记忆这个信息以便快速查找。

文本匹配过程:

当使用AC自动机进行文本匹配时,会从根节点开始,针对输入文本中的每个字符进行状态转换。

如果当前节点有一个对应当前字符的子节点,就沿着黑色的子节点弧线进行转换。

如果没有对应的子节点,就沿着蓝色的后缀弧线转移到另一个状态,这个状态是当前节点所有可能后缀中最长的一个存在于Trie树中的状态。
在每次状态转换时,都会检查当前节点是否是一个蓝色节点(即字典中的单词),或者通过绿色的字典后缀弧线是否可以到达一个蓝色节点。如果是,那么就找到了一个匹配。

通过这种方式,AC自动机能够在文本中高效地找到所有字典中的单词,时间复杂度是线性的,即与文本的长度成正比。这使得AC自动机在诸如文本搜索、网络内容过滤和生物信息学等领域的字符串匹配问题中非常有用。

如果大家有兴趣的话不妨看看各语言 AC 自动机的视线源码,可以理解的更为透彻一点

源码实现

Java 版 AC 自动机
go 版 AC 自动机
其他

引用

用最直观的方式解释 AC 自动机
Aho–Corasick algorithm

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

吴恩达机器学习全课程笔记第三篇

目录 前言 P42-P48 神经元和大脑 神经网络中的层 更复杂的神经网络 前向传播(做出预测) P49-P53 代码中的推理 构建一个神经网络 P54-P60 矩阵乘法 TensorFlow框架实现神经网络 前言 这是吴恩达机器学习笔记的第三篇,第二篇笔记…

绿盾限制终端网络访问权限会恢复后,别的网站访问正常就是无法访问钉钉网站和下载东西

环境: Win10 专业版 钉钉7.5.5 绿盾7.0 问题描述: 绿盾限制终端网络访问权限会恢复后,别的网站访问正常就是无法访问钉钉网站和下载东西 解决方案: 排查方法 1.重置浏览器或者更换浏览器测试(未解决&#xff09…

nc开发刚导入项目eclipse出现莫名其妙的错误,红叉,感叹号,文件missing

解决类出现红叉 解决感叹号,文件missing 其他问题 右上角的视图,要选择java,如果是javaEE也会有一些文件没有展示出来。

QYWX企业微信的公告信息限制保存pdf的破解

公司使用企业微信好几年,重大的消息使用公告信息这个模块。可重要的消息无法保存,只能在线收藏。这个玩意只考虑到了维护企业利益,无视员工利益。 后来发现可以利用windows的虚拟打印机,将公告打印成pdf。 用了一段时间&#xf…

IOT-Reaserch安装ghidra以及IDEA和ghidra的配置

Linux research 5.4.0-91-generic #102~18.04.1-Ubuntu SMP Thu Nov 11 14:46:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux java --version IOT自带的java是符合要求的,不需要额外下载 iotresearch:~/install-file$ java --version openjdk 11.0.13 2021-10-19 …

【Quasar】quasar轮播图进度条

效果 开始效果 即将结束 结束 码 <template><q-carouselv-model"slide"transition-prev"scale"transition-next"scale"swipeableanimatedinfiniteautoplaynavigationpaddingarrowsheight"300px"class"bg-primary text…

PHP实现分离金额和其他内容便于统计计算

得到的结果可以粘贴到excel计算 <?php if($_GET["x"] "cha"){ $tips isset($_POST[tips]) ? $_POST[tips] : ; $pattern /(\d\.\d|\d)/; $result preg_replace($pattern, "\t\${1}\t", $tips); echo "<h2><strong>数…

ESRI中国培训资料(2013-2018年)

一、2013年培训资料 链接&#xff1a;https://pan.baidu.com/s/1BDQbOlpXGjEE3nLsQowJJg?pwd4j7v 提取码&#xff1a;4j7v 二、2014年培训资料 链接&#xff1a;https://pan.baidu.com/s/1DiDMgrIMz2D-XCAh8jCncA?pwdbfs9 提取码&#xff1a;bfs9 三、2015年培训资料 …

css实现梯形

<div class"trapezoid"></div> .trapezoid {width: 200px;height: 0;border-bottom: 100px solid red; /* 定义梯形的底边 */border-left: 50px solid transparent; /* 定义梯形的左边 */border-right: 50px solid transparent; /* 定义梯形的右边 */} …

Java 2:运算符、表达式和语句

2.1 运算符与表达式 Java提供了丰富的运算符&#xff0c;如算术运算符、关系运算符、逻辑运算符、位运算符等。Java语言中的绝大多数运算符和C语言相同&#xff0c;基本语句如条件分支语句&#xff0c;循环语句等&#xff0c;也和C语言类似。 2.1.1算术运算符与算术表达式 1…

Redis的常见面试题

目录 前言 Redis支持哪些数据类型 五种核心类型 Zset为什么用跳表不用红黑树 &#xff1f; Redis常见的应用场景&#xff1f; 如何检测Redis的连通性&#xff1f; 如何设置key的过期时间&#xff1f; Redis为什么是单线程模型&#xff1f; Redis里的IO多路复用是什…

[计网底层小探索]:实现并部署多线程并发Tcp服务器框架(基于生产者消费者模型的线程池结构)

文章目录 一.网络层与传输层协议sockaddr结构体继承体系(Linux体系)贯穿计算机系统的网络通信架构图示: 二.实现并部署多线程并发Tcp服务器框架线程池模块序列化反序列化工具模块通信信道建立模块服务器主体模块任务回调模块(根据具体应用场景可重构)Tips:DebugC代码过程中遇到…

MySQL学习笔记3: MySQL数据库基础

目录 前言目标数据库操作&#xff08;针对database 的操作&#xff09;1. 创建数据库 create database 数据库名;2. 查看数据库 show databases;3. 选中数据库 use 数据库名;4. 删除数据库 drop database 数据库名; mysql中支持的数据类型1. 数值类型: NUMERIC(M,D)2. 字符串类…

linux platform架构下I2C接口驱动开发

目录 概述 1 认识I2C协议 1.1 初识I2C 1.2 I2C物理层 1.3 I2C协议分析 1.3.1 Start、Stop、ACK 信号 1.3.2 I2C协议的操作流程 1.3.3 操作I2C注意的问题 2 linux platform驱动开发 2.1 更新设备树 2.1.1 添加驱动节点 2.1.2 编译.dts 2.1.3 更新板卡中的.dtb 2.2 …

良好的 API 安全策略的重要性

根据 Cloudflare 2024 年 API 安全与管理报告&#xff0c;到 2024 年&#xff0c;API 请求占全球动态互联网流量的 57%&#xff0c;这证实 API 是现代软件开发的重要组成部分。但随着多年来它们的采用不断增加&#xff0c;相关的安全挑战也随之增加。 在过去两年中&#xff0c…

“目标检测”任务基础认识

“目标检测”任务基础认识 1.目标检测初识 目标检测任务关注的是图片中特定目标物体的位置。 目标检测最终目的&#xff1a;检测在一个窗口中是否有物体。 eg:以猫脸检测举例&#xff0c;当给出一张图片时&#xff0c;我们需要框出猫脸的位置并给出猫脸的大小&#xff0c;如…

Meta 发布 MMCSG (多模态智能眼镜对话数据集)

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

FFmpeg的HEVC解码器源代码学习笔记-1

一直想写一个HEVC的码流解析工具&#xff0c;看了雷神264码流解析工具&#xff0c;本来想尝试模仿写一个相似的265码流分析工具&#xff0c;但是发现265的解码过程和结构体和264的不太一样&#xff0c;很多结构体并没有完全暴露出来&#xff0c;没有想到很好的方法获得量化参数…

HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例

HAL STM32 HW I2C DMA SSD1306/SH1106驱动示例 &#x1f4cd;硬件I2C DMA驱动参考&#xff1a;https://blog.csdn.net/weixin_45065888/article/details/118225993 &#x1f516;本工程基于STM32F103VCT6&#xff0c;驱动程序独立&#xff0c;可以移植到任意STM32型号上使用。…

VSCODE中使用Django处理后端data和data models

链接&#xff1a; Python and Django tutorial in Visual Studio Code MVC的理解 在实际的程序中采用MVC的方式进行任务拆分。 Model&#xff08;模型&#xff09;负责封装应用程序的数据和业务逻辑部分。Model包含数据结构&#xff0c;数据处理逻辑以及相关的操作方法&#…