文章目录

  • 1. 多模式串匹配
  • 2. 经典多模式串匹配--AC自动机
    • 2.1 AC自动机构建
    • 2.2 在AC自动机上匹配主串
    • 2.3 复杂度分析
  • 3. python包

1. 多模式串匹配

  • 前面学的BF、RK、BM、KMP都是单模式串匹配算法(一个模式串,一个主串)
  • 多模式串匹配,即在一个主串中查找多个模式串(Trie树是多模式匹配)
  • 比如实现多个敏感词过滤;单模式需要一遍遍的,扫描,过滤,扫描,过滤;多模式扫描一遍,过滤完成

2. 经典多模式串匹配–AC自动机

AC自动机算法(Aho-Corasick算法),是在Trie树之上,加了类似 KMP 的 next 数组。

class ACNode    //AC自动机的Trie树节点类,假设只有26个字母的数据集
{public:char data;ACNode *children[charNum];size_t count;   //记录这个节点被多少个单词占用bool isEndOfWord;//是否是一个单词的结束字符size_t freq;    //单词插入的频次int length;     //当isEndOFWord为True时,记录模式串长度ACNode *fail; //失败指针ACNode(char ch = '/'):data(ch), isEndOfWord(false),count(0), freq(0),length(-1),fail(NULL){memset(children,0,sizeof(ACNode*) * charNum);}~ACNode(){}
};

2.1 AC自动机构建

  • 1,将多个模式串插入Trie树。
  • 2,在Trie树上构建失败指针(相当于KMP中的失效函数 next 数组)



void buildFailPointer()
{queue<ACNode*> ACNode_queue;ACNode_queue.push(root);ACNode *p, *pchild, *q, *qchild;int i;while(!ACNode_queue.empty())//用队列按层遍历{p = ACNode_queue.front();//队首的节点pACNode_queue.pop();for(i = 0; i < charNum; ++i){pchild = p->children[i];//找到p的非空子节点pcif(pchild == NULL)continue;if(p == root)pchild->fail = root;else{q = p->fail;    //q为p的失效指针while(q != NULL)    //q不为空{qchild = q->children[pchild->data-'a'];//字符等于pc的qcif(qchild != NULL)//qc存在{pchild->fail = qchild;//链接pc失败指针到qcbreak;//找到了就跳出循环}q = q->fail;//qc不存在,就再去上一个失效点找}if(q == NULL)//最后找到root处还没找到pchild->fail = root;//pc的失效指针指向root}ACNode_queue.push(pchild);//把p的非空子节点pc入队}}
}

2.2 在AC自动机上匹配主串

void match(const string &maintext)  //maintext是主串
{int n = maintext.size();ACNode *p = root, *temp;//模式串从root开始int index, pos;for(int i = 0; i < n; ++i)//主串从i=0开始{index = maintext[i]-'a';//子节点下标while(p->children[index] == NULL && p != root){//p不为root,且 子节点为空(找不到那个i对应的字符)p = p->fail;    //失败指针发挥作用的地方}p = p->children[index];if(p == NULL)p = root;   //如果没有匹配的,从root开始重新匹配temp = p;while(temp != root)//打印出可以匹配的模式串{if(temp->isEndOfWord == true){pos = i-temp->length+1;cout << "Found " << maintext.substr(pos,temp->length) << " at ""position(start from 0) "<< pos << " at " << maintext << endl;}temp = temp->fail;}}
}

主程序

Trie textlib;
string a("abcd"), b("bcd"), c("c");
textlib.insert(a);
textlib.insert(a);
textlib.insert(b);
textlib.insert(c);
textlib.buildFailPointer();
textlib.match("abcdc");


在Trie树基础上的AC自动机完整代码(请点击查看)

2.3 复杂度分析

  • 构建AC自动机
  1. 构建Trie树,时间复杂度O(m*len),其中len表示敏感词平均长度,m 表示敏感词个数
  2. 构建失败指针,每个节点构建失败指针不会超过len次(树的平均高度),整个失败指针就是O(k*len), k 是节点个数
  • 匹配复杂度
    for循环依次遍历主串中每个字符,for循环内部的while复杂度O(len),总的复杂度O(n*len),敏感词不会很长,所以近似于O(n)

3. python包

https://pypi.org/project/ahocorasick-python/
https://pypi.org/project/ahocorasick-rs/

字符串匹配算法(AC自动机 Aho-Corasick)相关推荐

  1. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

  2. go regexp匹配字符串_多模式字符串匹配算法ac自动机(用go语言实现)

    本文主要包括三部分内容 字典树 建立ac自动机 ac自动机匹配规则 字典树 字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计,排序和保存大量的字符串(但不仅限 ...

  3. Aho-Corasick 多模式匹配算法(AC自动机) 的算法详解及具体实现

    多模式匹配 多模式匹配就是有多个模式串P1,P2,P3-,Pm,求出所有这些模式串在连续文本T1-.n中的所有可能出现的位置. 例如:求出模式集合{"nihao","ha ...

  4. 字符串处理 —— AC 自动机

    [概述] KMP 算法用于解决长文本的单模板匹配问题,字典树用于解决单个单词(短文本)多模板匹配问题,而 AC 自动机用于解决的是长文本的多模板匹配问题,其是以 trie 树的结构为基础,结合 KMP ...

  5. 字符串算法 | AC自动机算法

    1.简介 一种多模式串匹配算法, 可以快速从主串中同时找出所有包含的所有模式串. 对比KMP是单模式匹配, 虽然可以使用单模式串匹配算法逐个进行查找模式串, 但是实际场景中,若模式串的数量可能很大,并 ...

  6. 字符串(AC自动机(fail tree))

    传送门 注意:注释中的那段代码是不能用的 #include<iostream> #include<cstdio> #include<cstring> #includ ...

  7. 【算法无用系列】AC自动机敏感词过滤

    简介: 本文是博主自身对AC自动机的原理的一些理解和看法,主要以举例的方式讲解,同时又配以相应的图片.代码实现部分也予以明确的注释,希望给大家不一样的感受.AC自动机主要用于多模式字符串的匹配,本质上 ...

  8. 提高篇 第二部分 字符串算法 第4章 AC自动机

    https://blog.csdn.net/wangyh1008/article/details/81428056 [模板]AC自动机(加强版) 洛谷3796 AC自动机_A_loud_name-CS ...

  9. TypeScript:Aho–Corasick算法实现敏感词过滤

    敏感词过滤应该是许多后端同事经常会遇到的需求,无论是评论.弹幕.文章,都需要做敏感词过滤处理来规避风险.在前端开发中,使用replace函数来替换字符串是我们的常规操作,在这之前我思考过如果用Java ...

  10. 模板 - AC自动机

    ACM-ICPC模板 目录 求有多少个模式串在文本串里出现过 建fail树dfs求每个模式串在文本串中的出现次数 ac自动机fail树上dfs序建可持久化线段树 AC自动机是一种多模匹配算法 AC自动 ...

最新文章

  1. 【数据库】兴唐第二十七节课之jdbc的使用
  2. TIOBE 5 月编程语言榜单:Python 超越 Java 重回第二,Rust 崛起
  3. picACG本地缓存目录_7天用Go动手写/从零实现分布式缓存GeeCache
  4. 《C和指针》学习备忘
  5. 大疆口袋云台 最大存储卡_佳能云台相机专利曝光:可换镜头设计,将与大疆竞争...
  6. 2019了,转行学编程过时了吗?
  7. 指针01:指针的定义与使用
  8. 被替换的项目不是替换值长度的倍数_机器学习中处理缺失值的9种方法
  9. 有约束的最小二乘方图像复原方法_matlab图像复原算法
  10. 计算机软件研究方法与技术路线,毕业论文研究方法与技术路线
  11. Win11预览版更新错误怎么办?Win11预览版安装失败的解决方法
  12. openCV利用航拍相机从底部向上扫描物体拼接全景图
  13. python远程访问服务器获取文件
  14. 月是故乡明,每逢佳节倍思亲,近乡情更怯
  15. 软件工程——形式化方法概述
  16. 【单片机毕业设计】【mcuclub-jj-026】基于单片机的垃圾桶的设计
  17. 2019HDU多校第十场
  18. 拍照 识别 翻译 云脉慧眼
  19. JS之Web API
  20. 湖南文旅数据中心:湖南文旅数据早知道(9月10日)

热门文章

  1. windows API 串口编程参考
  2. mysql和mybatis面试题_BATJ面试题汇总详解:MyBatis+MySQL+Spring+Redis+多线程
  3. C++ 初始化与赋值
  4. nodeJs的学习之路(1)
  5. 第1章 ssh命令和SSH服务详解
  6. 使用export/import导出和导入docker容器
  7. MediaPlayer 播放视频的方法
  8. 【转】java单例模式的实现
  9. Bootloader启动过程
  10. Prim最小生成树算法