Aho_Corasick_Automaton
写一篇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相关推荐
- 每日一题 2019/4/8
今天就整理模板吧 感谢牛逼网友的帮助,有了这些模板整理工具: https://github.com/4thcalabash/code_library http://www.planetb.ca/syn ...
- [USACO 2012 January Gold] Video Game Combos
题目描述 贝西在玩电脑游戏!在游戏中,键盘的'A','B'和'C'三个按键是唯一可用的.贝西可以根据她的需要随意按这几个键.但是游戏里只有N(1 <= N<= 20)种招式.一个招式命令就 ...
- BZOJ 1009 GT考试 (AC自动机 + 矩阵乘法加速dp)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 准考证号为\(n\)位数\(X_1X_2....X_n(0<=X_ ...
- BZOJ 4327: JSOI2012 玄武密码 ACAM
title BZOJ 4327 LUOGU 5231 简化题意: 给定一个长度为 \(N\) 的母串,求 \(M\) 个字符串其前缀在母串上的最大匹配长度. analysis 先构建 \(Trie\) ...
- BZOJ 2938: [Poi2000]病毒 ACAM
title BZOJ 2938 LUOGU 24444 简化题意: 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 ACAM+fail树
title BZOJ 2434 LUOGU 2414 Description 打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B.P 两个字母,是这样工作的: 输入小写字 ...
- Duan2baka的AC自动机模板!
HDU[2222] Keywords Search 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机常用于多模字符串匹配问题 代码如下 ...
最新文章
- 【组队学习】【28期】数据采集从入门到精通
- Python实现ARP欺骗
- spring 登录提示 Bad credentials
- 唐山师范学院计算机宿舍,唐山师范学院宿舍条件怎么样宿舍图片内景
- explain的用法_这次是真拯救了我,MySQL索引优化,explain讲得非常清楚了
- c/c++ 标准库 string
- 服务器客户端通信协议,Redis服务端-客户端通信协议
- vivado和modelsim联合仿真实现占空比1:15的分频
- 免装版_ProeWildfire 5.0 免装版 安装教程详解
- java 原型模式的应用_java中原型模式详解和使用方法
- 【气动学】基于matlab气动力导弹姿态控制【含Matlab源码 969期】
- html5的file api,HTML5 File API
- YUV格式的图片查看工具YUView 2.13
- word 2016 页码从任意页开始
- 腾讯后端面试题python_python技术面试题(十九)--腾讯
- 实现自己的日志打印系统
- Rancher Labs获2000万美元B轮融资, CEO 梁胜出任有容云联席CTO
- Android高德地图贴合图片完成手绘地图展示
- Android-MPChart:PieChart使用小记
- Java代码实现解压文件包和压缩文件的工具类