自动机

数据结构与算法系列----AC自动机

帅比萌擦擦* 提交于 2019-12-04 18:28:37
一:概念 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。一个常见的例子就是给出n个单词,再给出一段文章(长度是m),让你找出有多少个单词在文章里出现过。要搞懂AC自动机,先得有字典树Trie的基础知识(也有人说需要KMP的知识,我觉得暂且不要理会这个。但是在看这篇文章之前,Trie字典树,你是必须要先搞懂,如果你还不理解Trie,请参考 http://blog.csdn.net/laojiu_/article/details/50838421 )。 与其他字符匹配不同,KMP算法是单模式串的字符匹配算法,AC自动机是多模式串的字符匹配算法。匹配时间复杂度是O(N),线性复杂度! 二:算法过程(三步走) 举个例子,假如现在给出5个模式串:say she shr he her 主串是:yasherhs 现在问你,这5个模式串有几个出现在主串里的? OK,现在就拿这个例子来完成这个算法的过程。 第一步: 构建Trie树,这很简单的了。构建好后,出现下图: 第二步: 构建失败指针 构建失败指针是AC自动机的核心所在,玩转了它也就玩转了AC自动机,失败指针就是,当我的主串在trie树中进行匹配的时候,如果当前节点不能再继续进行匹配,那么我们就会走到当前节点的fail节点继续进行匹配。

(模板)AC自动机模板

孤街浪徒 提交于 2019-12-04 17:39:51
1. 给出模式串和文本串,文本串长度小于1e6,模式串长度之和小于1e6,求文本串中有多少模式串出现。 题目链接:https://www.luogu.org/problem/P3808 AC code: /* luoguP3808 (AC自动机模板题) 求文本串中有多少模式串出现 */ #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<cstdlib> using namespace std; const int maxn=1e6+5; struct Tree{ //Trie树 int fail,vis[30],key; //key用来记录有几个单词以这个节点结尾 }AC[maxn]; int n,cnt; char s[maxn]; //在Trie树中插入结点 void build(char *s){ int len=strlen(s),u=0; for(int i=0;i<len;++i){ int t=s[i]-'a'; if(!AC[u].vis[t]) AC[u].vis[t]=++cnt; u=AC[u].vis[t]; } AC[u].key+=1; } //构建fail指针 void get_fail(){ queue<int> que; for(int i

NFA转换为等价的DFA

◇◆丶佛笑我妖孽 提交于 2019-12-03 13:05:58
 在编译系统中,词法分析阶段是整个编译系统的基础。对于单词的识别,有限自动机FA是一种十分有效的工具。有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA。在非确定的有限自动机NFA中,由于某些状态的转移需从若干个可能的后续状态中进行选择,故一个NFA对符号串的识别就必然是一个试探的过程。这种不确定性给识别过程带来的反复,无疑会影响到FA的工作效率。因此,对于一个非确定的有限自动机NFA M,经常的做法是构造一个确定的有限自动机DFA M’。  有穷自动机(也称有限自动机)作为一种识别装置,能准确地识别正规集,即识别正规文法所定义的语言和正规式所表示的集合。引入有穷自动机理论,正是为词法分析程序的自动构造寻找特殊的方法和工具。 有穷自动机分为两类:确定的有穷自动机(Deterministic Finite Automata,DFA)和不确定的有穷自动机(Nondeterministic Finite Automata,NFA)。下面分别给出确定的有穷自动机和不确定的有穷自动机的定义、与其有关的概念、不确定的有穷自动机的确定化以及确定的有穷自动机的化简等算法。   NFA转换为等价的DFA: 在有穷自动机的理论里,有这样的定理:设L为一个由不确定的有穷自动机接受的集合,则存在一个接受L的确定的有穷自动机。这里不对定理进行证明,只介绍一种算法

「总结」后缀自动机

不打扰是莪最后的温柔 提交于 2019-12-03 13:04:46
最近刷了一下后缀自动机。 题其实做了也不少了,稍微有一点理解。(教练:得理解深刻) 1.我个人认为$parent$树其实是一颗虚树(最近又学了虚树,做了三道题),虚树的思想是只留存关键点以及关键点的$lca$。 $parent$树其实相当于后缀树的虚树,只留存了一些关键点。可以发现对于同一个$right$集合来说,在后缀树上有很多节点的$right$集合是完全相同的,这样在后缀树上这些节点其实是一段从上到下的连续的,度为1的节点。$SAM$把它们压在一起,用$MIN,MAX$的长度来代表这个节点所包含的集合(对于给定的$right$集合,只要再给出长度就可以确定子串),这样实现了对后缀树空间的优化。 2.$trans$转移边是相当于在结尾加入字符,$parent$树边其实是相当于在开头加入字符。 3.每个前缀节点都会丢失一个后缀信息(就是最长前缀,因为无法再从前面加字符了)。 4.$len$值代表的是一条从原点经过$trans$边到达某个节点的最长路径。 5.$parent$树上前缀节点与其父亲的$len$相减就是本质不同子串个数。 题列(全是板子题): 1. 弦论 如果是本质不同的话,只需要强制每个节点的$right$集合大小为$1$即可,先$dp$一次求出路径数(从某个点开始的路径数等于从这个点代表的前缀所包含的子串个数),这样直接在$trans$上从小到大枚举转移即可。

用有限自动机(DFA)实现字符串匹配

纵然是瞬间 提交于 2019-12-03 12:12:06
这个算法在算法导论上写的很晦涩,而且还搞了一大堆定义和推导。其实背后的想法很naive。 既然要做字符串匹配,那就构造一个有限自动机出来:对于长度为n的pattern,如果当前字符串匹配上了一个字符,那么自动机的状态就是1;如果当前字符串匹配上了两个字符,那么自动机的状态就是2,……如果当前字符串把整个pattren都匹配了,那么自动机的状态就是n(也就是pattern的长度)。 现在问题来了,待匹配的字符串是千变万化的,怎么办?自动机的核心——状态转移函数——应该是什么样的?注意到,状态转移函数要对每个状态和每个可能的输入都有明确的定义,所以,只能对每个状态,都把整个字母表遍历一遍。 对于每个pattern,都有一个自动机;每个自动机也只和pattern有关(当然也和字母表有关,但是和待匹配的字符串无关)。 例如,pattern是“ababc”,待匹配的字符串是“abababc”那么,当字符串已经匹配了“abab”的时候(此时自动机的当前状态是4),下一个输入字符是“a”,那么,自动机的下一个状态应该是多少呢?稍微思考10秒钟,发现自动机的下一个状态应该是3。——这就是所谓的额后缀函数的本质。 然后按照这个思路想下去,得到的结论和算法导论上讲的那一堆晦涩难懂的东西,是一样的。 来源: https://www.cnblogs.com/adgjl/p/11795769.html

编译原理:非确定的自动机NFA确定化为DFA

你说的曾经没有我的故事 提交于 2019-12-03 05:20:12
1.设有 NFA M=( {0,1,2,3}, {a,b},f,0,{3} ),其中 f(0,a)={0,1} f(0,b)={0} f(1,b)={2} f(2,b)={3} 画出状态转换矩阵,状态转换图,并说明该NFA识别的是什么样的语言。 解析: a b 0 {0,1} 0 1 2 2 3 3 状态转换图如下:                        识别语言为:(a | b)*abb 2.NFA 确定化为 DFA 1.解决多值映射:子集法 1). 上述练习1的NFA 解析: 根据1的NFA构造DFA状态转换矩阵如下: a b A {0} {0,1} {0} B {0,1} {0,1} {0,2} C {0,2} {0,1} {0,3} D {0,3} {0,1} {0}   根据1的NFA构造DFA状态转换图如下:      识别语言:b*aa*(ba)*bb, 与1的NFA的识别的语言相同,都是以abb结尾的字符串的集合。 2). P64页练习3 状态转换矩阵如下: 0 1 A {S} {Q,V} {Q,U} B {Q,V} {V,Z} {Q,U} C {V,Z} {Z} {Z} D {Q,U} {V} {Q,U,Z} E {V} {Z} F {Q,U,Z} {V,Z} {Q,U,Z} G {Z} {Z} {Z} 状态转换图如下:                  

非确定的自动机NFA确定化为DFA

僤鯓⒐⒋嵵緔 提交于 2019-12-03 05:15:01
1.设有 NFA M=( {0,1,2,3}, {a,b},f,0,{3} ),其中 f(0,a)={0,1} f(0,b)={0} f(1,b)={2} f(2,b)={3} 画出状态转换矩阵,状态转换图,并说明该NFA识别的是什么样的语言。 2.NFA 确定化为 DFA 1.解决多值映射:子集法 1). 上述练习1的NFA 2). P64页练习3 2.解决空弧:对初态和所有新状态求ε-闭包 1). 发给大家的图2 2).P50图3.6 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合。 步骤: 1).根据NFA构造DFA状态转换矩阵 ①确定DFA的字母表,初态(NFA的所有初态集) ②从初态出发,经字母表到达的状态集看成一个新状态 ③将新状态添加到DFA状态集 ④重复23步骤,直到没有新的DFA状态 2).画出DFA 3).看NFA和DFA识别的符号串是否一致。 来源: https://www.cnblogs.com/SeBr7/p/11779579.html

非确定的自动机NFA确定化为DFA

对着背影说爱祢 提交于 2019-12-03 05:08:28
1.设有 NFA M=( {0,1,2,3}, {a,b},f,0,{3} ),其中 f(0,a)={0,1} f(0,b)={0} f(1,b)={2} f(2,b)={3} 画出状态转换矩阵,状态转换图,并说明该NFA识别的是什么样的语言。 2.NFA 确定化为 DFA 1.解决多值映射:子集法 1). 上述练习1的NFA 2). P64页练习3 2.解决空弧:对初态和所有新状态求ε-闭包 1). 发给大家的图2 2).P50图3.6 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合。 步骤: 1).根据NFA构造DFA状态转换矩阵 ①确定DFA的字母表,初态(NFA的所有初态集) ②从初态出发,经字母表到达的状态集看成一个新状态 ③将新状态添加到DFA状态集 ④重复23步骤,直到没有新的DFA状态 2).画出DFA 3).看NFA和DFA识别的符号串是否一致。 来源: https://www.cnblogs.com/hzxx/p/11779294.html

第八次作业 非确定的自动机NFA确定化为DFA

微笑、不失礼 提交于 2019-12-03 04:51:04
1.设有 NFA M=( {0,1,2,3}, {a,b},f,0,{3} ),其中 f(0,a)={0,1} f(0,b)={0} f(1,b)={2} f(2,b)={3} 画出状态转换矩阵,状态转换图,并说明该NFA识别的是什么样的语言。 状态转换矩阵: a b 0 0,1 0 1 2 2 3 3 状态转换图: 识别的语言:(a|b)*abb 2.NFA 确定化为 DFA 1.解决多值映射:子集法 1). 上述练习1的NFA 状态转换矩阵: a b 0 0 {0,1} {0} 1 {0,1} {0,1} {0,2} 2 {0,2} {0,1} {0,3} 3 {0,3} {0,1} {0} 状态转换图: 2). P64页练习3 状态转换矩阵: 0 1 1 {S} {V,Q} {Q,U} 2 {V,Q} {V,Z} {Q,U} 3 {V,Z} {Z} {Z} 4 {Q,U} {V} {Q,U,Z} 5 {Q,U,Z} {Q,U} {Q,U,Z} 6 {V} {Z} 7 {Z} {Z} {Z} 状态转换图: 2.解决空弧:对初态和所有新状态求ε-闭包 1). 发给大家的图2 2).P50图3.6 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合。 步骤: 1)

10.30 非确定的自动机NFA确定化为DFA

孤人 提交于 2019-12-03 04:43:20
1.设有 NFA M=( {0,1,2,3}, {a,b},f,0,{3} ),其中 f(0,a)={0,1} f(0,b)={0} f(1,b)={2} f(2,b)={3} 画出状态转换矩阵,状态转换图,并说明该NFA识别的是什么样的语言。 答:(1)状态转换矩阵 (2)状态转换图 (3)该NFA识别的语言是b*aa*bb 2.NFA 确定化为 DFA   1.解决多值映射:子集法     1). 上述练习1的NFA      答:构造DFA状态转换矩阵          画出DFA:          2). P64页练习3      答:构造DFA状态转换矩阵       画出DFA        2.解决空弧:对初态和所有新状态求ε-闭包     1). 发给大家的图2     答:构造DFA状态转换矩阵      画出DFA          2).P50图3.6      答:状态转换矩阵:       状态转换图: 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合。 步骤: 1).根据NFA构造DFA状态转换矩阵 ①确定DFA的字母表,初态(NFA的所有初态集) ②从初态出发,经字母表到达的状态集看成一个新状态 ③将新状态添加到DFA状态集 ④重复23步骤