写一篇AC自动机的博客。(以HDU 2222为例)
AC自动机是支持多模式串匹配的自动机,它基于Trie树通过Fail指针的跳转来实现快速统计。

首先为AC自动机的节点结构体:

    struct AC_Node{int end;int fail;int next[SIGMA];}n[MN];

其中end表示以此节点为终止的单词个数;fail表示当在此节点失配后可以转移到得前缀最长的节点编号;next数组表示此节点的SIGMA个后继节点。

insert函数表示向AC自动机中插入字符串s[ ];从根节点(下标为零)开始逐层推进;最后在单词末尾的节点上更新此节点的end:

void Aho_Corasick_Automaton :: insert(char s[])
{int i = 0, k, now = 0;while (s[i] != '\0') {k = s[i] - 'a';if (n[now].next[k] == 0)n[now].next[k] = ++cnt;now = n[now].next[k];i ++;}n[now].end ++;
}

build函数为从Trie树向AC自动机的构造;因为此函数主要功能为得到Fail数组,所以也可以叫它getFail函数;通过与KMP类似的思想,每次通过已知的节点信息更新它们的子节点,更新子节点时通过推进队列来实现连续跳转:

void Aho_Corasick_Automaton :: build()
{queue < int >que;for (int i = 0;i < SIGMA; i ++) {if (n[0].next[i] != 0) {n[n[0].next[i]].fail = 0;que.push(n[0].next[i]);}}while (! que.empty()) {int now = que.front();que.pop();for (int i = 0;i < SIGMA; i ++) {if (n[now].next[i] != 0) {n[n[now].next[i]].fail = n[n[now].fail].next[i];que.push(n[now].next[i]);}else n[now].next[i] = n[n[now].fail].next[i];}}
}

最后是query操作 : 如果失配就跳到它的Fail指针,并将此节点的信息传递给它的Fail指针:

int Aho_Corasick_Automaton :: query(char s[])
{int now = 0, ans = 0, i = 0, k;while (s[i] != '\0') {k = s[i] - 'a';now = n[now].next[k];int t = now;while (t && n[t].end != -1) {ans += n[t].end;n[t].end = -1;t = n[t].fail;}i ++;}return ans;
}
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;const size_t MN = 1000005, SIGMA = 26, root = 0;
int N;
char tmp[MN];int cnt = 0;struct Aho_Corasick_Automaton{struct AC_Node{int end;int fail;int next[SIGMA];}n[MN];void clear() ;void insert(char s[]) ;void build() ;int query(char s[]) ;}ac;void Aho_Corasick_Automaton :: clear()
{cnt = 0;memset(n, 0, sizeof(n));
}void Aho_Corasick_Automaton :: insert(char s[])
{int i = 0, k, now = 0;while (s[i] != '\0') {k = s[i] - 'a';if (n[now].next[k] == 0)n[now].next[k] = ++cnt;now = n[now].next[k];i ++;}n[now].end ++;
}void Aho_Corasick_Automaton :: build()
{queue < int >que;for (int i = 0;i < SIGMA; i ++) {if (n[0].next[i] != 0) {n[n[0].next[i]].fail = 0;que.push(n[0].next[i]);}}while (! que.empty()) {int now = que.front();que.pop();for (int i = 0;i < SIGMA; i ++) {if (n[now].next[i] != 0) {n[n[now].next[i]].fail = n[n[now].fail].next[i];que.push(n[now].next[i]);}else n[now].next[i] = n[n[now].fail].next[i];}}
}int Aho_Corasick_Automaton :: query(char s[])
{int now = 0, ans = 0, i = 0, k;while (s[i] != '\0') {k = s[i] - 'a';now = n[now].next[k];int t = now;while (t && n[t].end != -1) {ans += n[t].end;n[t].end = -1;t = n[t].fail;}i ++;}return ans;
}int main()
{int Q;scanf("%d", &Q);while (Q --){ac.clear();scanf("%d", &N);for (int i = 1;i <= N;i ++) {scanf("%s", tmp);ac.insert(tmp);}ac.n[0].fail = 0;scanf("%s", tmp);ac.build();printf("%d\n", ac.query(tmp));}return 0;
}

Aho_Corasick_Automaton相关推荐

  1. 每日一题 2019/4/8

    今天就整理模板吧 感谢牛逼网友的帮助,有了这些模板整理工具: https://github.com/4thcalabash/code_library http://www.planetb.ca/syn ...

  2. [USACO 2012 January Gold] Video Game Combos

    题目描述 贝西在玩电脑游戏!在游戏中,键盘的'A','B'和'C'三个按键是唯一可用的.贝西可以根据她的需要随意按这几个键.但是游戏里只有N(1 <= N<= 20)种招式.一个招式命令就 ...

  3. BZOJ 1009 GT考试 (AC自动机 + 矩阵乘法加速dp)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 准考证号为\(n\)位数\(X_1X_2....X_n(0<=X_ ...

  4. BZOJ 4327: JSOI2012 玄武密码 ACAM

    title BZOJ 4327 LUOGU 5231 简化题意: 给定一个长度为 \(N\) 的母串,求 \(M\) 个字符串其前缀在母串上的最大匹配长度. analysis 先构建 \(Trie\) ...

  5. BZOJ 2938: [Poi2000]病毒 ACAM

    title BZOJ 2938 LUOGU 24444 简化题意: 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码 ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机 ACAM+fail树

    title BZOJ 2434 LUOGU 2414 Description 打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B.P 两个字母,是这样工作的: 输入小写字 ...

  7. Duan2baka的AC自动机模板!

    HDU[2222] Keywords Search 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机常用于多模字符串匹配问题 代码如下 ...

最新文章

  1. 【组队学习】【28期】数据采集从入门到精通
  2. Python实现ARP欺骗
  3. spring 登录提示 Bad credentials
  4. 唐山师范学院计算机宿舍,唐山师范学院宿舍条件怎么样宿舍图片内景
  5. explain的用法_这次是真拯救了我,MySQL索引优化,explain讲得非常清楚了
  6. c/c++ 标准库 string
  7. 服务器客户端通信协议,Redis服务端-客户端通信协议
  8. vivado和modelsim联合仿真实现占空比1:15的分频
  9. 免装版_ProeWildfire 5.0 免装版 安装教程详解
  10. java 原型模式的应用_java中原型模式详解和使用方法
  11. 【气动学】基于matlab气动力导弹姿态控制【含Matlab源码 969期】
  12. html5的file api,HTML5 File API
  13. YUV格式的图片查看工具YUView 2.13
  14. word 2016 页码从任意页开始
  15. 腾讯后端面试题python_python技术面试题(十九)--腾讯
  16. 实现自己的日志打印系统
  17. Rancher Labs获2000万美元B轮融资, CEO 梁胜出任有容云联席CTO
  18. Android高德地图贴合图片完成手绘地图展示
  19. Android-MPChart:PieChart使用小记
  20. Java代码实现解压文件包和压缩文件的工具类

热门文章

  1. 去掉office标题前的黑点
  2. H5之微信授权登陆 (uniapp网页版微信授权登录)
  3. RS-485总线,这篇很详细
  4. Oracle for update skip locked 详解
  5. Win10 KeilC51-C251-ARM共存方法
  6. 斗牛(牛牛)概率计算器
  7. ISTP概况及网络版检索方法
  8. 南开大学2017年数学分析高等代数考研试题
  9. 自控原理学习笔记-系统稳定性分析(1)-BIBO稳定及Routh判据
  10. 常用计算机病毒防治办法,常见的计算机病毒防治措施有哪些