AC自动机入门题目(HDU
来源:互联网 发布:淘宝电脑详情页尺寸 编辑:程序博客网 时间:2024/05/21 04:43
AC自动机其实就是 字典树+KMP。 最开始的时候我没有刷字典树的题目,所以不是很能理解, 但是刷完字典树之后,对AC自动机得理解就比较简单了。
AC自动机的构造中有3个需要注意的地方:
1、next[i][j] 这个next里面存的值和字典树的是几乎一样的(不过也有些不同,下面我会解释的)。存放的是当前所在第i个节点当下一个出现的字符为j的时候的节点位置。
2、fail[i] 这个和kmp中fail是一样的,当前第i个节点失配的话,那就去尝试匹配第fail[i] 里面存放的节点。
**以上就是字典树与kmp的合体,不过不同的是:1、在字典树中如果当前节点为i的话, 如果没有为j的节点, 那么next[i][j] == -1; 但是在AC自动机中里面会存放是,当前i节点的失配指针指向的节点中如果有同样j的节点那么就会next[i][j]指向它,如果其失配指针(fail[i])没有j节点的,那么就找fail[fail[i]] 中的j节点是否存在, 直到一直找到根为止。
2、在构建fail[i]的时候用的是这样的思路(BFS),如果在当前节点失配,那么就去找当前节点的父亲节点的失配指针指向的节点中是否有i节点,如果有就指向它,否则就在去找它的失配节点, 一直到找到或者到根为止。**
3、temp指针,其实在AC自动机里面每次沿着字典树走,每当走到一个新的节点,就会沿着当前节点的失配节点一直往上走,看是否有匹配的节点;
比如 字典树中有这两个字符 acdm, cd.
现在要求匹配的acdmk, 如果没有temp的话就只会找到acdm,但是有了temp指针,就能当走到acdm中的d的时候就可以匹配到cd了。
本人较懒没有附加图片,多多画图,和体会一下,应该就可以懂了的。
#include <iostream>#include <stdio.h>#include <algorithm>#include <cstring>#include <queue>#include <cmath>#include <math.h>#include <stack>#include <vector>using namespace std;#define Max_N 500010struct Trie{ int next[Max_N][26], fail[Max_N], end1[Max_N]; int root, L; int newnode() { for (int i = 0; i < 26; i++) next[L][i] = -1; end1[L++] = 0; return L-1; } void init() { L = 0; root = newnode(); } void insert(char buf[]) { int len = strlen(buf); int now = root; for (int i = 0; i < len; i++) { if (next[now][buf[i] - 'a'] == -1) next[now][buf[i]-'a'] = newnode(); now = next[now][buf[i] - 'a']; } end1[now]++; } void build() { queue<int> q; fail[root] = root; for (int i = 0; i < 26; i++) if (next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; q.push(next[root][i]); } while (!q.empty()) { int now = q.front(); q.pop(); for (int i = 0; i < 26; i++) if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; q.push(next[now][i]); } } } int query(char buf[]) { int len = strlen(buf); int now = root; int res = 0; for (int i = 0; i < len; i++) { now = next[now][buf[i] - 'a']; int temp = now; while (temp != root) { res += end1[temp]; end1[temp] = 0; temp = fail[temp]; } } return res; }};char buf[1000010];Trie ac;int main(){ int T; int n; scanf("%d", &T); while (T--) { scanf("%d", &n); ac.init(); for (int i = 0; i < n; i++) { scanf("%s", buf); ac.insert(buf); } ac.build(); scanf("%s", buf); printf("%d\n", ac.query(buf)); } return 0;}
- AC自动机入门题目(HDU
- HDU 2222 Keywords Search (AC自动机入门题目)
- hdu 2222 AC自动机入门
- hdu 2222 -AC自动机入门
- HDU 2222 AC自动机经典题目
- hdu 2222(AC自动机入门题)
- hdu 2222(ac自动机入门题)
- 【AC自动机详解+入门模板】HDU 2222
- hdu 2222 AC自动机入门详解
- hdu 2222 Keywords Search ac自动机入门
- AC自动机入门+模板 (HDU 2222)
- HDU 2222 AC自动机 入门题
- HDU 2222 ac自动机入门模板题
- HDU 2222 AC自动机入门题
- AC自动机-题目集合
- AC自动机入门题(HDU 2222 + HDU 2896)
- AC自动机入门
- HDU2222 AC自动机入门
- Banner简单使用
- git 拉取远程代码
- 2017 多校训练第二场 HDU 6045 Is Derek lying?
- POJ 3261 Milk Patterns 最长出现k次的子串长度(后缀数组)
- 2017年JavaScript框架---Top5
- AC自动机入门题目(HDU
- Jersey过滤器
- D
- CS231n课程笔记翻译4:最优化笔记
- Mysql语句总结(2)
- Java多线程-----CopyOnWriteArrayList
- php数值转换时间及时间转换数值代码示例
- cartographer源码分析(17)-sensor-point_cloud.h
- 变矩器和发动机匹配