字符串匹配算法4:AC算法(1)理解

1. 背景(问题的提出)

假设您有一个文本包括 n个单词words 和 大量关键字 有m 个关键字keywords,请问你如何快速找到所有关键字?
首先想到的是简单的暴力匹配,两个for循环遍历查找
即如下所示:

//遍历所有单词 n个 words
//遍历所有关键字 m个 keywords
for(int i =0; i < n; i++)
{
	for(int j =0; j < m; j++)
	{
		if(keywords[j] == words[i])
		{
			printf("find keywords[j] %s ",keywords[j]);
		}
	}
}

这样时间复杂度为O(n*m),是非常缓慢的,
那么:有没有更高效的算法实现呢?

2. AC算法

2.1 AC算法-定义

1975年,贝尔实验室的Alfred Aho和Margaret Corasick发现了一种只扫描一遍文本就能完成这项任务的算法,该算法依据他们的名字命名为Aho-Corasick匹配算法,简称AC算法

2.2 AC算法-特点

  1. 只扫描一遍文本就能完成这项任务的算法
  2. 通过有限自动机巧妙地将字符比较转化为状态转移

2. AC算法-时间复杂度

算法的时间复杂度与关键字的数目无关,只跟文本长度有关,
其时间复杂度为O(n),优于O(n*m),匹配效率提升m倍。

3. AC算法实现步骤

3.1 两步:

第一步,我们将多个关键字构造成一个有限状态模式匹配机。
第二步,我们将文本字符串作为输入送入模式匹配机进行匹配。

ac自动机本质是一颗带状态的字典树

3.1 构建模式匹配机(三个核心函数)

在构建模式匹配机阶段,AC算法需要建立三个核心函数,分别为

  1. 转向函数goto
  2. 失效函数failure
  3. 输出函数output

4. 例子说明

下面通过关键字{he, she, his, hers}来介绍匹配机构建过程

4.1 转向函数(g)

在这里插入图片描述

  1. 定义: 转向函数(g):
    指的是一种状态之间的转向关系
  2. 公式:
    g(pre, x) = next,状态pre在输入一个字符x后转换为状态next,
  3. 例子:
    如 g(1, e) = 2。
  4. 问题:
    如果在模式串中不存在这个的转换,如g(5, r),怎么办呢?这个需要由失效函数来处理。

4.2 失效函数(f)

在这里插入图片描述

  1. 定义:
    指的是在失效情况下状态之间的转向关系
  2. 切换根据
    根据模式含有其他模式的前缀自动切换到某个状态
  3. 上图说明
    如上图模式串1含有模式串2的前缀,当匹配到a位置时,模式串1匹配失效,则跳转到模式串2进行匹配,而不用回到初始状态(0号状态)重新开始匹配。

4.2.1 she和hers例子

she模式是含有hers模式的前缀he,当在状态5匹配失效时跳转到状态2继续匹配。
在这里插入图片描述

4.2.2 递归推导

  1. 失效跳转状态可通过递归推导获得:
    f(与状态0直连状态) = 0 //f(1)=f(3)=0
    f(current) = g(f(pre),x) //f(4)=g(f(3),h)=g(0,h)=1

  2. 举例说明:
    比如g(5, r)=fail,g(5, r)=g(f(5),r),f(5)=g(f(4),e)=g(g(f(3),h),e)
    状态3对应字符s,没有其他模式的前缀,切换到状态0,即f(3)=0
    所以:
    f(5)=g(f(4),e)=g(g(f(3),h),e)=g(g(0,h),e)=g(1,e)=2,
    g(5, r)=g(f(5),r)=g(2,r)=8

4.2.3 {he, she, his, hers}的失效函数

在这里插入图片描述
状态转移图的失效函数转移函数:

 i 	1 2 3 4 5 6 7 8 9 
f(i)0 0 0 1 2 0 3 0 3

转移图如下所示:
在这里插入图片描述

4.3 输出函数(output)

  1. 定义
    输出函数: 指的是状态和模式串之间的一种关系。

  2. 说明: output(i)={P},表示当状态机达到状态i时,模式串P中的所有模式串已经完成匹配。比如达到状态5,则模式串she和he匹配成功。

  3. 输出函数如下图所示:

    i output(i)
    2 {he}
    5 {she,he}
    7 {his}
    9 {hers}

4.4 完整模式匹配机(图示)

在这里插入图片描述

5. 匹配例子(hisshers)

  1. 假设待匹配文本为"hisshers"
  2. 那么状态转移为:
    0->1->6-> 7->3 -> 0->3 ->4-> 5->2 ->8->9,文本仅扫描了一遍,依次输出结果"his"、“she”、“he”、“he”、“hers”。

6. 代码实现

代码实现请看第篇博客
字符串匹配算法4:AC算法(2)代码实现
https://blog.csdn.net/lqy971966/article/details/106359472

参考

https://mp.weixin.qq.com/s/YPD7FtVmtMysQXSetZdbOQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值