AC自动机

众所周知,AC自(bu)动机是可以自动wa的一种算法(不是

首先,AC自动机解决什么问题?

------多字符串匹配问题

算法原理是什么?

其基本思想,是字典树+KMP(仅为思想),字典树建树,随后根据KMP的思路进行点的匹配与跳转(感觉也有点像并查集)。

【1】、建树方式

与普通字典树一模一样

void insert(string str) {int p = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a';if (!st[p][t])st[p][t] = ++idx;p = st[p][t];}cnt[p]++;
}

【2】、点的匹配与跳转

其原理,是寻找后缀与前缀相同的点,进行跳转连接。

void built() {queue<int>q;for (int i = 0; i < 26; i++)if (st[0][i])q.emplace(st[0][i]);while (!q.empty()) {int k = q.front();q.pop();for (int i = 0; i < 26; i++) {int p = st[k][i];if (!p)st[k][i] = st[ne[k]][i];else {ne[p] = st[ne[k]][i];q.emplace(p);}}}
}

这段代码里,st数组记录字符间相连的线段,首先先将所有与根节点相连的字符串加入队列。

ne数组则代表点跳跃的地方,当p为0时,代表当前节点无后续节点,将其指向ne数组指定位置的后续节点,由此在匹配时,可以迅速找到某穿字符相匹配的后续字符串,不需跳回之前的节点;否则,更新节点p的指向,指向ne数组指定位置的后续节点,并加入队列。

因为当前字符串后缀的后缀一定包含在指向字符串前缀的后缀,因此不需要找到所有的后缀,只需连接最长的后缀即可,不须多次跳转,相当于路径压缩了。

【3】、匹配方式

先看代码

int findstr(string str) {int res = 0, p = 0, j = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a';j = st[j][t];p = j;while (p) {res += cnt[p];cnt[p] = 0;//依据题意判断是否归零p = ne[p];}}return res;
}

res:记录当前字符串匹配成功的数量

j:当前跑到的节点

p:从当前节点依次找到所有满足的后缀。

每次更新j的时候,因前面有

if (!p)st[k][i] = st[ne[k]][i];

因此,它能够跳转到最长后缀组成的前缀字符串的后续节点上,若不匹配则接着跳,直到匹配成功或回归0点。

当匹配成功时,会依次找到所有满足其后缀的地方(找后缀的后缀),然后计算字符串匹配数目。

例题

ACwing 1282. 搜索关键词

给定 n 个长度不超过 5050 的由小写英文字母组成的单词,以及一篇长为 m 的文章。

请问,有多少个单词在文章中出现了。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。

输出格式

对于每组数据,输出一个占一行的整数,表示有多少个单词在文章中出现。

数据范围

1≤n≤1e4
1≤m≤1e6

输入样例

1
5
she
he
say
shr
her
yasherhs

输出样例

3

代码

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
#include<queue>using namespace std;const int N = 10005, S = 51, M = 1000010;int st[N * S][26], cnt[N * S], idx;
string str;
int ne[N * S];
int m, n;void insert(string str) {int p = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a';if (!st[p][t])st[p][t] = ++idx;p = st[p][t];}cnt[p]++;
}void built() {queue<int>q;for (int i = 0; i < 26; i++)if (st[0][i])q.emplace(st[0][i]);while (!q.empty()) {int k = q.front();q.pop();for (int i = 0; i < 26; i++) {int p = st[k][i];if (!p)st[k][i] = st[ne[k]][i];else {ne[p] = st[ne[k]][i];q.emplace(p);}}}
}int findstr(string str) {int res = 0, p = 0, j = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a';j = st[j][t];p = j;while (p) {res += cnt[p];cnt[p] = 0;p = ne[p];}}return res;
}int main() {ios::sync_with_stdio(false);int t;cin >> t;while (t--) {memset(st, 0, sizeof st);memset(ne, 0, sizeof ne);memset(cnt, 0, sizeof cnt);idx = 0;cin >> n;while (n--) {cin >> str;insert(str);}built();cin >> str;cout << findstr(str) << endl;}return 0;
}

AC自动机(写的很乱,仅记录留作自己复习)相关推荐

  1. 【uva11019-Matrix Matcher】AC自动机+优化+记录

    http://acm.hust.edu.cn/vjudge/problem/33057 题意:在二维文本串T中查找一个二维模板串P出现了多少次. 题解: 拆分模板串P的每一行,建AC自动机. 拆分文本 ...

  2. 模板 - AC自动机

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

  3. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  4. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  5. P5357 【模板】AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数)

    P5357 [模板]AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数) 传送门 形式上,AC 自动机基于由若干模式串构成的 Trie 树,并在此之上增加了一些 fail 边:本质 ...

  6. HDU 2222 Keywords Search (AC自动机模板题)

    一组数据: 1 3 sss sss sss sss ans:3 #include <cstdio> #include <cstdlib> #include <vector ...

  7. 问题 D: AC自动机(二分,第一个等于和最后一个等于)

    问题 D: AC自动机 时间限制: 1 Sec 内存限制: 128 MB [提交][状态][讨论版] 题目描述 天降伟人 PK 又公开了他的新发明:AC自动机--一种可以自动 AC 题目的神秘装置. ...

  8. CodeForces - 1437G Death DBMS(AC自动机fail树上树链剖分建线段树/暴跳fail)

    题目链接:点击查看 题目大意:给出 n 个模式串,每个模式串初始时的权值为 0,然后有 m 次操作: 1 i x:将第 i 个模式串的权值修改为 x 2 s:给出一个字符串 s,询问字符串 s 作为主 ...

  9. YBTOJ:单词频率(AC自动机)

    解析 我对力量一无所知 通过这题,可以看出我对AC自动机还是完全没有理解 qwq 首先容易想到: 建一课trie树,然后建树时记录每个串s的终点,这个点后面每被经过一次,就相当于出现一次该单词s 但是 ...

最新文章

  1. 2022-2028年中国木制拼板玩具市场调查研究报告
  2. java工程师占比_Java过时了吗?
  3. 鸟哥的Linux私房菜(基础篇)- 第十六章、例行性工作排程 (crontab)
  4. 使用 cmd、PowerShell 等用命令行的方式创建文件及文件夹
  5. 关于删除数据仓库的数据
  6. 密度图的密度估计_箱形图、小提琴图、直方图……统统可以卡通化!
  7. tidevice.exceptions.MuxServiceError: Could not start service: com.apple.testmanagerd.lockdown.secure
  8. YbtOJ#652-集合比较【Treap】
  9. ICDAR 2019 文本识别冠军方案将开源!
  10. Illustrator 教程,如何在 Illustrator 中使用图层组织内容?
  11. [工具开发] 移动梦网短信发送客户端
  12. vc浏览器_【36氪基金X一刻】零基础VC/PE行研标准班7月10日线上开课
  13. ProGuard:类混淆,类的指定函数保留
  14. c语言工程作业,西工大c语言程序作业
  15. 以太坊基础开发入门教程,完整入门【转】
  16. 补剂课堂:补充肌酸的最佳时机
  17. 类和对象5:绑定和静态、类、抽象方法
  18. 玩转Luat 进阶篇③——远程升级实现过程详解
  19. 游戏界面设计艺术性的思考
  20. 基于全卷积神经网络的前列腺磁共振图像分割

热门文章

  1. 第三次学JAVA再学不好就吃翔(part78)--List类
  2. 20应用统计考研复试要点(part2)--统计学
  3. scikit_learn中fit()/transform()/fit_transform()区别和联系
  4. SAP 电商云 Spartacus UI 的自定义 hamburger 菜单
  5. 动态创建 @ViewChild 导致运行时错误的原因分析
  6. 通过 SAP UI5 的 TypeScript 开发环境,来学习什么是 DefinitelyTyped
  7. SAP Spartacus develop branch 的服务器端渲染启动方式
  8. SAP Spartacus Page Layout - 页面布局设计
  9. sap gateway data provider - /IWFND/IF_MGW_CORE_RUNTIME
  10. 如何在ui5 xml view中使用嵌入的自定义css style