自动机

AC自动机——搜索关键词

限于喜欢 提交于 2020-02-08 18:50:43
搜索关键词 给定 n 个长度不超过 50 的由小写英文字母组成的单词,以及一篇长为 m 的文章。 请问,有多少个单词在文章中出现了。 输入格式 第一行包含整数 T,表示共有 T 组测试数据。 对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。 输出格式 对于每组数据,输出一个占一行的整数,表示有多少个单词在文章中出现。 数据范围 1 ≤ n ≤ 1 0 4 1≤n≤10^4 1 ≤ n ≤ 1 0 4 , 1 ≤ m ≤ 1 0 6 1≤m≤10^6 1 ≤ m ≤ 1 0 6 输入样例: 1 5 she he say shr her yasherhs 输出样例: 3 题解: 第一道ac自动机的题,相对于kmp,ac自动机就是把一维的信息放在了树上来进行统计了。 # include <bits/stdc++.h> using namespace std ; const int N = 1e4 + 7 , S = 55 , M = 1e6 + 7 ; int ne [ N * S ] , con [ N * S ] , tr [ N * S ] [ 26 ] , cnt ; char str [ M ] ; queue < int > q ; void insert ( ) { int p = 0 ; for ( int i = 0

后缀自动机

两盒软妹~` 提交于 2020-02-08 02:30:58
#include<bits/stdc++.h> using namespace std; const int maxn = 2e6+9;//一般有2n个等价类 int tot=1,las=1; char s[maxn]; long long ans=0; struct NODE { int ch[26]; int len,fa; NODE() { memset(ch,0,sizeof(ch)); len=fa=0; } } dian[maxn]; void add(int c)//构造自动机 { int p=las,np=las=++tot; dian[np].len=dian[p].len+1; for(; p&&!dian[p].ch[c]; p=dian[p].fa) dian[p].ch[c]=np; if(!p)dian[np].fa=1; else { int q=dian[p].ch[c]; if(dian[q].len==dian[p].len+1) dian[np].fa=q; else { int nq=++tot; dian[nq]=dian[q]; dian[nq].len=dian[p].len+1; dian[q].fa=dian[np].fa=nq; for(; p&&dian[p].ch[c]==q; p=dian[p].fa) dian[p].ch

【AC自动机_每个模式串在文本串中出现的次数】HDU 3065 病毒侵袭持续中

霸气de小男生 提交于 2020-02-07 05:02:06
HDU 3065 病毒侵袭持续中 题意:给出n个全是英文大写字母的模式串,保证每个模式串不完全相同。然后再给出一个文本串,字符集由包含ASCII可见字符组成。问每个模式串在文本串中出现的次数。 一: 思路:其实就是一个AC自动机的板子???只是分别统计了每个模式串出现的次数而已???真的是这样!!!!!我真的迷…… #include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxN = 50004; const int maxS = 2000006; char str[1005][55]; struct AC_automat{ int trie[maxN][26], tot; int fail[maxN];

洛谷 P3808 【模板】AC自动机(简单版)

最后都变了- 提交于 2020-02-05 21:34:15
洛谷 P3808 【模板】AC自动机(简单版) 【洛谷AC自动机详解】 【是先看了洛谷详解大致理解了,又看这个深度理解了fail指针和trie图以及query函数】 #include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxN = 1000000 + 7; struct AC_automat{ int trie[maxN][26], tot; int fail[maxN], sum[maxN]; void Clear(int rt) { for(int i = 0; i < 26; i ++ ) trie[rt][i] = 0; sum[rt] = 0 ; } void init() { tot = 0

AC自动机

不问归期 提交于 2020-02-03 21:20:55
例题:洛谷 P3808 AC自动机 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct Tree { //字典树 5 int fail;//失配指针 6 int vis[26];//子节点的位置 7 int end;//标记有几个单词以这个节点结尾 8 } AC[1000000];//Trie树 9 10 int cnt = 0;//Trie的指针 11 int n; 12 string s; 13 14 void Build(string s) { 15 int l = s.size(); 16 int now = 0;//字典树的当前指针 17 for (int i = 0; i < l; i++) {//构造Trie树 18 if (AC[now].vis[s[i] - 'a'] == 0)//Trie树没有这个子节点 19 AC[now].vis[s[i] - 'a'] = ++cnt;//构造出来 20 now = AC[now].vis[s[i] - 'a'];//向下构造 21 } 22 AC[now].end += 1;//标记单词结尾 23 } 24 void Get_fail() {//构造fail指针 25 queue<int> Q;//队列 26 for (int i = 0; i <

loj2278. 「HAOI2017」字符串

余生颓废 提交于 2020-02-01 10:54:14
2278. 「HAOI2017」字符串 给出一个字符串 $ s $ 和 $ n $ 个字符串 $ p_i $,求每个字符串 $ p_i $ 在 $ s $ 中出现的次数。注意这里两个字符串相等的定义稍作改变。 给定一个常数 $ k $,对于两个字符串 $ a, b $,如果 $ a = b $,那么满足: 1. $ |a| = |b| $; 2. 对于所有 $ a_i \neq b_i $ 以及 $ a_j \neq b_j $,满足 $ |i-j| < k $。 如果 $ |a| = |b| \le k $,那么认为 $ a = b $。 写在前面:注意!!这题我还没有调出来! 因为这是一道多模板串题,我们考虑AC自动机。 它的要求相当于中间可以有一段长度为k-1的不匹配,其他都要匹配。 那么我们吧所有p的正串建AC自动机,反串也建AC自动机。 对于一个节点x,假设它匹配到了某个串的第j位,对应的反串应该要匹配那个串的后j+k+1位。 那么我们记录下反串j+k+1的节点是哪一个,当成询问挂在x上。 我们在把s拿去跑AC自动机,同样把对应的j与j+k+1记录下来。 统计的时候相当于把j+k+1的位置+1,询问子树和。 有一个容斥我没有想的很清楚,先咕着 来源: https://www.cnblogs.com/liankewei/p/12247586.html

编译器-有穷自动机

孤者浪人 提交于 2020-02-01 10:24:10
决定性有穷自动机和非决定性有穷自动机的区别,每一步导向的状态是否是确定的,是否有 伊普西龙 (自由转换步) 他们都是识别正则语法的,DFA执行更快 实现步骤 词法解析 正则 NFA DFA 表驱动的DFA实现 正则到NFA实现的例子 A 表示0-无穷个的A相连 A+表示AA AB表示A语言后接着B语言 A+B表示A或者B语言都行 伊普西龙代表不需要输入,直接可以转换状态 a代表输入值为a (1+0)*1 eg 1 1111 10101001 0101001 NFA到DFA 把所有 伊普西龙(STATE)即一个state通过伊普西龙到达的所有状态归结为一个状态 ,再进行联系 来源: CSDN 作者: qq_38105524 链接: https://blog.csdn.net/qq_38105524/article/details/104130216

[GDKOI2013]大山王国的城市规划

孤者浪人 提交于 2020-01-31 09:13:14
一、题目 二、解法 建出回文自动机,自动机上的每一个节点都代表一个回文串,我们考虑一个串不是另一个串子串的问题。 分情况考虑,首先选的节点必须不同。然后就是两边个去掉一个字符(重复若干次)不能相等,反应到自动机上就是没有父子关系。还有一种就是不能是前缀后缀回文串,反应到自动机上就是 f a i l fail f a i l 树上没有父子关系。 构建一个有向图,把回文树和 f a i l fail f a i l 上的边当成有向边加进去(自动机上下连上),问题就变成了最长反链问题,即选最多的点,不存在任意两个点有路径,根据 Dilworth \text{Dilworth} Dilworth 定理,把原问题转化为最小链覆盖,用网络流求解即可。 关于最小连覆盖, 给出材料 。 蒟蒻作者自然是给不出代码的,实现就靠各位了。 来源: CSDN 作者: C202044zxy 链接: https://blog.csdn.net/C202044zxy/article/details/104105763

弱势图解AC自动机

别说谁变了你拦得住时间么 提交于 2020-01-28 17:19:48
本篇文章主要详细介绍$AC$自动机的$fail$指针: 如果有什么不完善的地方,请联系我$qwq$ 前置知识: 1、建议学一下$kmp$算法 2、$Trie$ 导入: AC自动机是用来解决多模板匹配问题的,但是,如果就单纯的把每个模板串拼接在一起,或者单个单个匹配的话,肯定是会超时的,而它的思想是把所有的模式串建立一颗$Trie$,然后用文本串来匹配,那么我们就必须在这颗$Trie$树上进行快速跳转来优化,于是,AC自动机就诞生了 重点:fail指针到底是什么? 我们先来思考一个问题,假如我们按照上面的思想,把每一个模式串建立一颗字典树,那么怎样才能在这个模板串失配后快速跳到下一个有可能成功匹配的字符串来匹配呢?我们举个例子:假设文本串是$bcde$,模式串有两个,分别为$bce$和$cd$,我们为两个模式串建一颗$Trie$,如下图: 我们拿着文本串开始匹配,发现匹配到$2$节点后,就失配了,也就是模式串$bce$失配,那么我们如何快速跳到下一个模式串$cd$来匹配呢?这个时候你可能会说,到$0$节点开始匹配呀,可是这样其实就是重头匹配下一个字符串了,效率并不高,在这里,我们其实可以直接跳到$4$号节点开始匹配,为什么?那是因为我们发现$2$号节点是成功匹配了的,只是不能到$3$号节点去,但是我们发现$2$号节点匹配说明了字符$c$在文本串出现过,那么$c$必定会匹配,所以$0

[学习笔记]AC自动机

和自甴很熟 提交于 2020-01-27 21:57:06
AC自动机 Aho-Corasick automaton 本文基本上是oiwiki的复制粘贴: https://oi-wiki.org/string/ac-automaton/ 可能加上了自己感性理解 概述 AC 自动机是 以 TRIE 的结构为基础 ,结合 KMP 的思想 建立的 建立AC自动机有两个步骤: TRIE:将所有的模式串构成一颗字典树 KMP:对TRIE上所有的状态构造失配指针 可以说,AC自动机是由字典树和失配指针构成的 回顾KMP KMP匹配算法可以在线性时间内判定字符串 \(A[1-N]\) 是字符串 \(B[1-M]\) 的子串,并求出字符串A在字符串B中各次出现的位置.有两个数组: \(next,f​\) \(next[i]​\) 表示的是 A中以i为结尾的非前缀子串 与 A的前缀 能够匹配的最长 长度 \(f[i]​\) 表示的是 B中以i为结尾的子串 与 A的前缀 能够匹配的最长 长度 一直说AC自动机就是树上的KMP,那这两者有什么关系呢? 字典树 insert() 字典树上的每个节点代表有限自动机一个状态,表示的是某个模式串的前缀。 编译原理学得超级差..( 模式串的结尾状态被称为 可接受状态 字典树的插入: void insert(char *s){ int u=0; for(int i=1;s[i];++i){ if(!tr[u][s[i]-'a