音无结弦之时,天使跃动之心。立于浮华之世,奏响天籁之音。.|

次林梦叶

园龄:3年3个月粉丝:22关注:2

编译原理--有穷自动机

image

from pixiv



有穷自动机

我们学习完后应该能够做到一件事:
正则表达式->NFA->DFA->识别

正则表达式->NFA

教程的P55和P56,57有详细过程

其实在真正考试的时候按照这个教程上写,当正则表达式有点复杂的时候,我们的ε会有点多,同时状态也有点多,这会导致下面将NFA->DFA有点复杂
我们可以简写,比如写a*的时候不按照教程上,而是就只简单地
image

NFA->DFA

  • 子集法

教程的P50,51,52有详细过程,但是不清楚,可以看如下两篇博客:
博客1
博客2

步骤一:从开始状态开始,将开始状态能够通过ε到达的所以状态加入集合,这个集合是我们DFA的开始状态A

步骤二:以开始状态A开始,对其中每一个状态元素,for 循环我们的输入集合,如{a,b,c,d....}
假设我们现在取出了状态集合A中的状态0,输入集合中的输入字符a
我们现在要看的就是0通过a到达哪些状态,同时到达的这些状态通过ε又可以到达哪些状态

注意我们可能会遇到一个情况如:状态1有两条边,1通过a到达2,1通过ε到达3(2没有ε的边,2不能到达3),如果这个时候我们有一个状态B={1},然后ε-closure(move(B,a))中是否有3呢?
答案是没有的,我们要按照书上定义的来:move(B,a)={2},然后ε-closure({2})={2}
所以是不会有3的

总的来说,我们将通过输入字符到达的状态和这些状态通过ε到达的状态 当做一个子集
我们将这个子集作为DFA的新找到状态B
然后我们将这个状态加入队列queue
每一次我们都取queue中的状态来更新出新的DFA的状态
(有点像BFS?)

总的来说,我们还是要填一个状态矩阵

DFA状态\输入集合 a b ... z
A C D ... B
B A C ...
... ... ... ... ...

然后我们就要开始画图了,注意:要标注出开始状态和终结状态,在DFA中的终结状态是包含NFA中终结状态的集合。

即我们通过ε-closure(move(xxx,xxx)) 得到的NFA状态集合,其DFA的一个状态,如果这个NFA状态集合包含了NFA的终结符号,那么在DFA中这个状态就是终结状态。

如下:
image


  • 分割法

这个方法主要是用来化简DFA的图

化简包括消除无用状态和合并等价状态(教程P52)

无用状态就是从DFA开始状态无论也到达不了的状态
对于无用状态我们的做法是(从图上看)删除掉这个状态节点同时删除掉它射入和射出的边

等价状态:某两个状态s和t是否等价要根据一致性条件和蔓延性条件(教程P53)

一致性条件:状态s和状态t必须同时为可接受状态(终态)或不可接受状态(非终态和不可达的状态)
蔓延性条件:对于所有输入符号,状态s和状态t必须转换到等价的状态里



比如:假设{0,1,2}{3,4}是两个状态集合

DFA状态\输入集合 a b c
0 1
1 0 1 0

判断一下0,1这两个状态是否等价?
答案是不等价的
0是不能通过a,c到达任何一个状态集合的,但是1可以,根据蔓延性条件,0状态和1状态通过相同的输入符合,但是不能转换到等价状态里,所以0,1状态并不等价



我们现在可以来总结一下,分割法的步骤:

  • 去除不可达的状态:即我们通过NFA->DFA这个过程画出来的 状态转换表,我们查看状态转换表,看看哪个状态是不能通过任何状态到达的 P53,找到了将这个状态去除

  • 将目前剩余的状态依据 是否为终态进行划分,这个时候应该得到了两个状态集。
    然后我们再通过输入符号,判断集合中的状态是否能够都能够到达相同的状态集中,不能则将这个状态从这个状态集中分离,加入与之等价的状态集中(没有则新开个状态集)。

  • 最后我们得到若干个状态集,将这些状态集重新编号,按照原始的状态转换表再画出一副新的状态转换表出来

  • 然后我们要开始画出DFA图来了,注意:要标注好终态和开始状态,与NFA->DFA一样的上,如果新的DFA状态包含原来DFA状态终态,那么这个DFA状态也是终态,包含原来DFA开始状态的为开始状态
    如:
    image

DFA->识别

教程P48有详细过程,其实就是根据DFA画出状态矩阵图,然后有手就行


有穷自动机(finite state automata)是一个识别器,它对每个输入的字符做识别和判断,以确定其能到达的最终状态或状态集和路径,有穷自动机分为两类,即不确定的有穷自动机NFA和确定的有穷自动机DFA.

image

image

首先要重点区别一下DFA和NFA:

  • DFA的初态是唯一的,而NFA不唯一
  • DFA和NFA的终止状态集都可以为空
  • DFA无法接受空串,但是NFA可以
    image
    还需要注意的是:有穷自动机可识别的语言是无穷的,但是状态却是有穷的

关于DFA和NFA的终止状态集都可以为空的讨论

image

结合上面解释举一个例子:

image

可以看到答案B中状态1是一个"死路",即进去了就出不来了,也就是说这条路走不通,不能往这里走


image




image

这里写错了,按照教程上的说法应该是到S的幂集
所谓幂集是:
image

举一个例子:

f(0,a)={0,3} f是转换函数,这种情况只有NFA才存在
因为DFA是经过转换函数后到原来的S集合元素中,只有NFA才有可能通过转换函数到原来的S集合元素组成的子集中去(教材P49)

读书随记

下面我们来到了词法分析这里,回顾下上次我们看的应该是文法。

我们说过一般涉及到语法树的,用的是上下文无关文法(即2型文法),因为语法树是下面我们进行语法分析时常常用的,所以在语法分析中我们用的基本是上下文无关文法

这里词法分析,我们用的是正规文法,他是单词形式化的描述工具,因为通过正规文法很容易地得到正规式(正则表达式),通过正则表达式我们可以构造出NFA和DFA出来。

通过正规文法得到的正规式也被称为正则表达式

然后的内容就是正规文法和正则表达式之间进行相互转换了(记得看看PTA上作错的作业)

DFA和NFA M是一个五元组:
M=(K,∑,f,S,Z)
K是有穷集,即表示状态机的状态
∑是输入符号集合
f是状态转换方式,如f(S,a)=U 表示状态S通过a到达状态U
S是初态,在DFA这里只要一个初态,在NFA是个集合
Z是终态,在DFA和NFA都是个集合

DFA的某个状态通过某个输入符号到达的状态是唯一的,但是NFA不是这样的

想下文法 G=(Vn,Vt,f,E),是四元组



image

对于这种题目我的建议是先通过NFA求出正规式来,再通过正规式求出正规文法


关于构造NFA时的简写方式

我们知道当我们通过正规式得到NFA时,如果NFA按照书上的方式构造,则状态太多,空也会很多,这将给我们再NFA->DFA时造成十分大的麻烦

下面一道例题给出简写方式:

image

可以看到,这里他将1,变成了自旋
将(01)
变成了两个节点之间相互转换的方式
这样节点非常少,很好些

同时需要注意下第3问,可以发现在第2问的DFA中A,B,C,D都是终结状态,A还是开始状态
根据书上P53,两个状态是等价则两个状态必须同时为可接受状态(终结状态)和不可接受状态;
根据上述这点,我们可以首先将{A,B,C,D}放在一个集合中
然后我们再根据 对于所有输入符号,两个状态必须转换到等价的状态里来进一步划分集合

一个比较神奇的地方:

我们知道在NFA->DFA时,我们需要将NFA的状态“打包”成集合当做DFA的状态,如果这个集合中含有NFA的终结状态,那么DFA也为终结状态,但是如果含有NFA的开始状态,那么DFA不一定是开始状态,DFA的开始状态是NFA的开始状态求ε-闭包 得到的。

比如下面这个题目:

image

像这种可以重复到开始符的NFA,一定到后面转化为DFA时,有较多个NFA的集合是包含NFA开始状态1的,但是DFA的开始符只有一个,即NFA的开始状态求ε-闭包 得到的。

image

本文作者:次林梦叶的小屋

本文链接:https://www.cnblogs.com/cilinmengye/p/17773718.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   次林梦叶  阅读(305)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起