Aho-Corasick算法学习
1、概述
Aho-Corasick自动机算法(简称AC自动机)1975年产生于贝尔实验室。该算法应用有限自动机巧妙地将字符比较转化为了状态转移。此算法有两个特点,一个是扫描文本时完全不需要回溯,另一个是时间复杂度为O(n),时间复杂度与关键字的数目和长度无关。
好了,我们先看下最原始的多模式匹配算法:
主串T,n=strlen(T)。
模式串Pi mi = strlen(pi)
for(i=0;i<n-MIN(m);++i) for(j=0;j<k;++j) if(n-mk<=n-i &&memcmp(T[i],Pk,mk)==0) printf(“match/n”);
是O(mn)的时间复杂度。
上面的算法很笨吧,下面看看聪明的AC算法是个啥意思。
2、 AC算法思想
AC算法思想:用多模式串建立一个确定性的树形有限状态机,以主串作为该有限状态机的输入,使状态机进行状态的转换,当到达某些特定的状态时,说明发生模式匹配。
下图是多模式he/ she/ his /hers构成的一个确定性有限状态机,做几点说明:
1、 该状态机优先按照实线标注的状态转换路径进行转换,当所有实线标注的状态转换路径条件不能满足时,按照虚线的状态转换路径进行状态转换。如:状态0时,当输入h,则转换到状态1;输入s,则转换到状态3;否则转换到状态0。
2、 匹配过程如下:从状态0开始进行状态转换,主串作为输入。如主串为:ushers,状态转换的过程是这样的:
3、 当状态转移到2,5,7,9等红色状态点时,说明发生了模式匹配。
如主串为:ushers,则在状态5、2、9等状态时发生模式匹配,匹配的模 式串有she、he、hers。
定义:
在预处理阶段,AC自动机算法建立了三个函数,转向函数goto,失效函数failure和输出函数output,由此构造了一个树型有限自动机。
转向函数,指的是一种状态之间的转向关系。g(pre, x)=next:状态pre在输入一个字符x后转换为状态next(上图中的实线部分)。如果在模式串中不存在这样的转换,则next=failstate。
失效函数,指的也是状态和状态之间一种转向关系。f(per)=next:是在比较失配的情况下使用的转换关系。在构造转向函数时,把不存在的转换用failstate表示,但是failstate不是一个具体的状态,状态机转换转换到failstate状态的时候就不知道该往哪转了。所以就要在状态机中找到一个有意义的状态代替failstate,当出现failstate状态时,自动切换到那个状态。
这个状态节点应该具有这样的特征:从这个状态节点向上直到树根节点(状态0)所经历的输入字符,和从产生failstate状态的那个状态节点向上所经历的输入字符串完全相同。而且这个状态节点,是所有具备这些条件的节点中深度最大的那个节点。如果不存在满足条件的状态节点,则失效函数为0。
累死了。举例子说吧,对状态9输入任何一个字符都会产生failstate状态,需要失效函数。状态3向上到状态0经过的输入字符串为s;而由状态9向上的输入字符串为sreh。字符串s相同,并且状态3是满足此条件的唯一节点,则
f(9)=3。
说来说去,失效函数就是要干这么件事儿:
意思就是说,在比较模式串1发生失配时,找一个模式串2,使得P2[0...j-1] = P1[i-j+1...i]。然后继续比较模式串2。看上面那个图,想起点儿什么东西没有?对了,是KMP算法。有人说AC算法就是KMP算法在多模式匹配情况下的扩展。
输出函数,指的是状态和模式串之间的一种关系。output(i)={P},表示当状态机到达状态i时,模式串集合{P}中的所有模式串可能已经完成匹配。
例:
模式串为:he/ she/ hers/ his 时,如上图所示:
转向函数:
失效函数:
输出函数:
3、 AC代码分析
下面的代码参考snort入侵检测系统开源软件的acsmx.c文件。
3.1数据结构分析
所有状态都被存储在一个ACSM_STATETABLE类型的数组中。
typedef struct {
int NextState[ ALPHABET_SIZE ];
int FailState;
ACSM_PATTERN *MatchList;
}ACSM_STATETABLE;
NextState对应转向函数;FailState对应失效函数;MatchList对应输出函数。
3.2代码分析
代码流程如下图:
Aho-Corasick算法学习相关推荐
- TypeScript:Aho–Corasick算法实现敏感词过滤
敏感词过滤应该是许多后端同事经常会遇到的需求,无论是评论.弹幕.文章,都需要做敏感词过滤处理来规避风险.在前端开发中,使用replace函数来替换字符串是我们的常规操作,在这之前我思考过如果用Java ...
- 拿下斯坦福和剑桥双offer,00后的算法学习之路
董文馨,00后,精通英语,西班牙语.斯坦福大学计算机系和剑桥大学双Offer,秋季将进入斯坦福大学学习. 10岁开始在国外上学:12岁学Scratch: 13岁学HTML & CSS: 14岁 ...
- 好久没有看到这么有建设性德文章,由衷地赞叹《知其所以然地学习(以算法学习为例)》-By 刘未鹏(pongba)
知其所以然地学习(以算法学习为例) By 刘未鹏(pongba) C++的罗浮宫(http://blog.csdn.net/pongba) Updated(2008-7-24):更新见正文部分,有标注 ...
- 原创 | 初学者友好!最全算法学习资源汇总(附链接)
在计算机发展飞速的今天,也许有人会问,"今天计算机这么快,算法还重要吗?"其实永远不会有太快的计算机,因为我们总会想出新的应用.虽然在摩尔定律的作用下,计算机的计算能力每年都在飞快 ...
- 基本算法学习(一)之希尔排序(JS)
参考书: 严蔚敏-数据结构 希尔排序(Shell's Sort) 希尔排序又称"缩小增量排序",归属于插入排序一类,简单来说,和我们的插入排序比,它更快. 奇妙的记忆点: 内排序( ...
- 大顶堆删除最大值_算法学习笔记(47): 二叉堆
堆(Heap)是一类数据结构,它们拥有树状结构,且能够保证父节点比子节点大(或小).当根节点保存堆中最大值时,称为大根堆:反之,则称为小根堆. 二叉堆(Binary Heap)是最简单.常用的堆,是一 ...
- Surf算法学习心得(一)——算法原理
Surf算法学习心得(一)--算法原理 写在前面的话: Surf算法是对Sift算法的一种改进,主要是在算法的执行效率上,比Sift算法来讲运行更快!由于我也是初学者,刚刚才开始研究这个算法,然而网上 ...
- 算法学习:后缀自动机
[前置知识] AC自动机(没有什么关联,但是看懂了会对后缀自动机有不同的理解) [解决问题] 各种子串的问题 [算法学习] 学习后缀自动机的过程中,看到了许多相关性质和证明,但是奈何才疏学浅(lan) ...
- 算法学习:后缀数组 height的求取
[前置知识] 后缀数组 [定义] [LCP]全名最长公共前缀,两个后缀之间的最长前缀,以下我们定义 lcp ( i , j ) 的意义是后缀 i 和 j 的最长前缀 [z函数] 函数z [ i ] 表 ...
- 算法学习:最小圆覆盖
[参考博客] https://www.cnblogs.com/bztMinamoto/p/10698920.html [定义] [圆]一个圆心和他的半径,就能够确定这个半径 [解决问题] 字面意思 给 ...
最新文章
- cos2x = cos^2x-sin^2x的推导
- AOC的显示器真的很烂
- unet图片数据增强_numpy实现深度学习遥感图像语义分割数据增强(支持多波段)
- android组件启动,Android四大组件Service之StartService启动
- 领域模型命名规约【PO,VO,POJO,BO,DTO,DO,JavaBean】
- C++/C--相对路径与绝对路径【转载】
- .NET开源项目介绍及资源推荐:数据持久层
- 工作实践 之 Google Guava 工具集的使用 ,提高效率
- 视觉SLAM笔记(39) 求解 ICP
- Vue源码之 Vue的生命周期
- es ik分词插件安装
- [翻译]用 Puppet 搭建易管理的服务器基础架构(3)
- 理解去中心化稳定币DAI
- 硬,软连接,以及在windows中的用法
- java中的时间片概念_java中常用的时间处理类TimeUtil
- LoadRunner11在Win10 下的破解解决办法(整合)
- 向量交点坐标公式_高中数学必修1-5常用公式(定理)
- python之Unitest框架
- Aggressive cows题解
- zemax设计35mm镜头_ZEMAX基础实例 - 变焦镜头设计