标准KMP算法用于单一模式串的匹配,即在母串中寻求一个模式串的匹配,但是现在又存在这样的一个问题,如果同时给出多个模式串,要求找到这一系列模式串在母串存在的匹配个数,我们应该如何处理呢?

基于KMP算法,我们能够想到的一个朴素算法就是,枚举这多个模式串,然后进行多次KMP算法,这个过程中完成计数,假设这里有n个模式串,那么整个算法的复杂度大约是O(n*m),m是母串的长度,这里的时间复杂度是粗略估计,没有计算辅助数组的时间(KMP中的next数组),但是这种复杂度还是太高,没有做到KMP算法中“成分利用已知信息”的核心思想,这里有一个巧妙的算法——AC自动机,能够线性的完成多模式串的匹配,即时间复杂度能够优化到O(m)。

下面简单的介绍一下解决多模式串匹配问题的AC自动机算法的思想。

回想起KMP所呈现的思想,我们在匹配之前需要充分挖掘模式串中所蕴含的信息,我们通过求得模式串的next数组,使得我们在遍历母串的时候得到了极大的优化,那么这里对于多模式串的匹配,应该采取相同的思路,我们应该对多个模式串所蕴含的信息进行充分挖掘。

由多模式串朴素的二维数组的存储,为了节省空间,我们又会联想到之前的字典树,这里我们基于多个模式串,建立一个字典树,然后线性扫母串的时候,就是在这样一个字典树上扫。

再次回想KMP中匹配过程,求得next数组时候,我们在母串上移动模式串完成匹配,基于next数组,我们得到的优化使得在模式串匹配失败之后,能够极大限度的往母串的右侧移动同时能够保证不漏掉任何匹配情况。但是在AC自动机这里,做法上有点区别,但是思想是一致的。做法上的区别体现在,基于多模式串的字典树上,我们将母串在字典树上进行匹配,我们在构造字典树的时候,记录模式串的最后一个字符作为终止节点,那么母串在字典树上匹配到终止节点的时候,就表明完成了一个模式串的匹配。

那么现在我们需要完成的就是匹配失败后的优化,在母串区间str[i]~str[j]匹配失败以后,最优的做法应该是,求得str[i]~str[j]这段字符串最长的公共前缀和与后缀和,然后继续从这个最长的前缀和这条支路下,继续进行匹配。为了完成这一步“极大限度的往母串的右侧移动同时能够保证不漏掉任何匹配情况”,我们在字典树每个节点处设置一个“匹配失败跳转”指针(下文统称fail指针),记录如果在该点匹配失败,最优化的情况下我们应该跳转到的字典树的位置。

能够看到,整个AC自动机呈现的多模式串匹配其实和KMP算法是高度的相似的。

那么下面就需要解决的问题就是,就像计算KMP中的next数组,这里我们如何计算字典树里的fail指针。

假设我们当前在找vi的fail指针,那么很显然,我们去找vi的父节点的fail指针所指向的节点vp,根据该指针的定义,很容易看到:

(1)    如果当前节点vp的子节点vj能够与vi匹配,那么vi的fail指针必然指向vj。

(2)    如果当前节点vp的子节点没有能够与vi匹配的,那么我们需要去找vp的fail指针指向的节点的子节点,看是否有与vi相互匹配的,没有的话,循环操作。

对于(2)似乎形成了一个递归模式,为什么会这样呢?或者说这样做的正确性体现在哪里呢?它源于fail指针的定义,仔细的读者应该能够看到,fail指针本质上是一个描述一个字符串最长的公共前缀与后缀,对于一段字符串str[i]~str[j],失配之后我们在该段字符串最长公共前后缀(记作str[p]~str[j])的基础上,添加那个导致失配的字符a,但是字典树中可能不存在这种情况,难道我们就因此重新开始新的匹配么?当然不,我们再找一下字符串str[p]~str[j]的最长公共前后缀(记作str[k]~str[j]),添加那个导致失配的字符a,然后循环操作……

这就是解决AC自动机的一个简答的思想描述。

能够看到它与KMP算法思想同步到了一致,这启示我们学习过程中的触类旁通,这种现象在很多地方也有着很明显的体现(积分、二重积分、三重积分;一元函数、多元函数;单一变量分布、多变量联合分布)。很多思维思想在一维的角度建立,然后推广到二维角度甚至更高维度。

AC自动机——多模式串匹配的算法思想的更多相关文章

  1. AC 自动机——多模式串匹配

    网站上的敏感词过滤是怎么实现的呢? 实际上,这些功能最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容后,通过字符串匹配算法来检查用户输入的内容是否包含敏感词. B ...

  2. AC自动机 - 多模式串匹配问题的基本运用 + 模板题 --- HDU 2222

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  3. Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例

    摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...

  4. AC自动机 - 多模式串的匹配运用 --- HDU 2896

    病毒侵袭 Problem's Link:http://acm.hdu.edu.cn/showproblem.php?pid=2896 Mean: 略 analyse: AC自动机的运用,多模式串匹配. ...

  5. AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora

    Problem's Link Mean: 有n个模式串和一篇文章,统计有多少模式串在文章中出现(正反统计两次). analyse: 好久没写AC自动机了,回顾一下AC自动机的知识. 本题在构造文章的时 ...

  6. AC自动机 - 多模式串的匹配运用 --- HDU 3065

    病毒侵袭持续中 Problem's Link:http://acm.hdu.edu.cn/showproblem.php?pid=3065 Mean: 略 analyse: AC自动机的运用. 这一题 ...

  7. (转)两种高效过滤敏感词算法--DFA算法和AC自动机算法

    原文:https://blog.csdn.net/u013421629/article/details/83178970 一道bat面试题:快速替换10亿条标题中的5万个敏感词,有哪些解决思路? 有十 ...

  8. HDU 2222:Keywords Search(AC自动机模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2222 KMP是单模式串匹配的算法,而AC自动机是用于多模式串匹配的算法.主要由Trie和KMP的思想构成. 题意 ...

  9. AC自动机基础知识讲解

    AC自动机 转载自:小白 还可参考:飘过的小牛 1.KMP算法: a. 传统字符串的匹配和KMP: 对于字符串S = ”abcabcabdabba”,T = ”abcabd”,如果用T去匹配S下划线部 ...

随机推荐

  1. setTimeout 和 setInterval区别

    setTimeout和setIntelval都有定时的功能!!!取消定时功能的时候,都有对应的clearTimeout以及clearInterval与之对应. 但是他们之间是有区别的! setTime ...

  2. Java MD5校验

    Java 生成MD5 MD5(Message Digest Algorithm),消息摘要算法,一般用于校验文件的完整性.Java内置已经实现了MD5,与SHA1算法,利用java.security. ...

  3. MySQL 连接数据库

    一.MySQL 连接本地数据库,用户名为“root”,密码“123”(注意:“-p”和“123” 之间不能有空格),缺点:密码显示在显示器上,容易泄露. C:\>mysql -h localho ...

  4. java-成员变量的属性与成员函数的覆盖

    java中在多态的实现是通过类的继承或者接口的实现来完成的. 在类继承或者接口实现过程中就会涉及到成员属性以及成员函数的重写,需要注意的是,成员函数的重写是直接覆盖父类的(继承中),但是成员变量重写是 ...

  5. 寒假的ACM训练三(PC110107/UVa10196)

    #include <iostream> #include <string.h> using namespace std; char qp[10][10]; int result ...

  6. Strategy 模式

    可以看到 Strategy 模式和 Template 模式解决了类似的问题,也正如在 Template 模式中分析的,Strategy模式和 Template 模式实际是实现一个抽象接口的两种方式:继 ...

  7. yum命令学习

    yum配置文件 /etc/yum.conf yum check-update检查一下有无更新 每天都要(设置定时任务todo) 1.列出所有可更新的软件清单---yum check-update 2. ...

  8. 微信菜单开发:使用PHP数组来定义微信菜单

    目前使用数组的方式来定义,然后在通过json_encode函数来转JSON $menuJson=array(); $menuJson['button'][]=array('name'=>urle ...

  9. jquery前端性能优化(持续添加。。。)

    1.选择器的使用 (1)$('#id')   使用id来定位dom元素是性能最高的方法.jQuery底层将直接调用本地方法document.getElementById().如果id直接可以找到所要对 ...

  10. memcached在windows安装

    下载地址: http://s3.amazonaws.com/downloads.northscale.com/memcached-win64-1.4.4-14.ziphttp://s3.amazona ...