NFA转DFA的子集构造(subset construction)算法

NFA转DFA的子集构造(subset construction)算法

之前学习编译原理的时候老师有讲过子集构造法,当时我以为自己听懂了,信心满满。可是这两天我做了一些题目,发现自己实际上还是太嫩了,学习浮于表面。之后又重新看了龙书和虎书,对子集构造法有了更深层次的了解。特此发出一篇文章分享我的经验。

1 概念

概念是我们学习编译原理的重中之重,虽然他很晦涩难懂,但我有必要将其放在最开始。

1.1 虎书概念

虎书的概念更偏向于理论化,我当时看的时候一头雾水,但是不要担心,之后会一点一点解释的

首先,我们形式化定义\epsilon闭包如下:

  • edge(s,c):状态s沿着标有c的边可到达的所有NFA状态的集合;
  • closure(S): 对于状态集合S,从S出发,只通过\epsilon边可以达到的状态集合;
    • 这种经过\epsilon边的概念可以用数学方法表述,即closure(S)是满足如下条件的最小集合T
      T=S \cup \left( \bigcup_{s \in T}edge(s,\epsilon) \right)
    • 我们可以用迭代法来算出T
      T \leftarrow S \\ repeat \ T' \leftarrow T \\ \qquad \quad T \leftarrow T' \cup \left( \bigcup_{s \in T'}edge(s,\epsilon) \right) \\ until \ T=T'

解释一下:当我们位于一个状态集合SS任意状态经过若干\epsilon能够到达的状态,都将包含在 closure(S) 里。

  • 龙书里将这个操作定义为\epsilon-closure(T)(T为状态集合)。

现在,假设我们位于由NFA状态s_i,s_k,s_l组成的集合d= \lbrace s_i,s_k,s_l \rbrace中。从d中的状态出发,输入符号c,将到达NFA新的状态集;我们称这个状态集为DFAedge(d,c)

  • DFAedge(d,c)=closure \left( \bigcup_{s \in d}edge(s,c) \right)

解释一下:将遍历集合d中的所有状态,得到 d 关于T=edge(s,c)的状态集,并对 Tclosure(T),得到的即为DFAedge(d,c)。简而言之,就是从一个状态集,经过一个输入到达的状态集为 T'=DFAedge(d,c)

利用DFAedge能更形式化地写出NFA模拟算法。如果初态是s_1,输入字符串是c_1,...,c_k,则算法为:

  • d \leftarrow closure( \lbrace s_1 \rbrace ) \\ for \ i \leftarrow 1 \ to \ k \\ \quad d \leftarrow DFAedge(d,c_i)

有了closureDFAedge算法,就能构造出DFADFA的状态d_1就是closure(s_1)。抽象而言,如果d_j=DFAedge(d_i,c)则存在一条从 d_id_j 的标记为 c 的边。令 \Sigma 是字母表:
states[0] \leftarrow \lbrace \rbrace; \qquad states[1] \leftarrow closure(\lbrace s_1 \rbrace)\\ p\leftarrow 1; \qquad j \leftarrow 0 \\ while \ j \leq p \\ \ \ \ foreach \ c \in \Sigma \\ \qquad e \leftarrow DFAedge(states[j],c) \\ \qquad if \ e =states[i] \ for \ some \ i \leq p \\ \qquad \quad \ then \ trans[j,c] \leftarrow i \\ \qquad \quad \ else \ p \leftarrow p+1 \\ \qquad \qquad \quad \, states[p] \leftarrow e \\ \qquad \qquad \quad \, trans[j,c] \leftarrow p \\ \; \; j \leftarrow j+1

解释一下:state[]代表了最终DFA的一个状态所对应的NFA状态集,s_1为初始状态,closure(\lbrace s_1 \rbrace)代表了初始状态s_1的闭包。上文中的代码实际上和龙书的代码一个意思,龙书的代码更加简单直白,所以这里可以跳过。等看完下面的龙书再回头来看

1.2 龙书概念

个人认为龙书的概念更加通俗易懂,但是由于没有数学公式的归纳,导致理论基础不扎实,有点慌。所以推荐两本书一起看。

首先,是概念:

  • 子集构造法的基本思想是让构造得到的DFA的每个状态对应NFA的一个状态集合。DFA在读入a_1a_2...a_n之后到达的状态应该对应于相应的NFA从开始状态出发,沿着以a_1a_2...a_n为边的路径能达到的状态的集合。

解释一下:概念很直观哈,我就不解释了^_^

接着,是算法:

  • 输入:一个NFA N
  • 输出:一个接受同样语言的DFA D
  • 方法:我们为算法 D 构造一个转换表DtranD的每个状态是一个NFA集合,构造Dtran,使得 D “并行地”模拟 N 在遇到一个给定输入串可能执行的所有动作。下面我们给出一些函数的定义
操作 描述
\epsilon - closure(s) 能够从NFA状态s开始只通过\epsilon转换到达的NFA状态集合
\epsilon - closure(T) 能够从T中某个NFA状态s开始只通过\epsilon转换到达的NFA状态集合,即 \bigcup_{s \in T} \epsilon -closure(s)
move(T,a) 能够从 T 中某个状态 s 出发通过标号为 a 的转换到达的NFA状态的集合
  • 在读入第一个符号之前,N可以位于集合\epsilon-closure(s_0)中的任何状态上 ,其中,s_0N 的开始状态。
  • 下面进行回归纳:假定N在读入输入串x之后可以位于集合T的任意状态上。如果下一个输入符号是 a,那么N可以立即移动到集合move(T,a)中的任何状态。然而,N 可以读入a之后再执行几个\epsilon转换,因此 N 在读入xa之后可以位于\epsilon-closure(move(T,a))中的任意状态上。接着我们可以构造出转换函数Dtran
    • 一开始,\epsilon-clusure(s_0)Dstates的唯一状态,且它未标记(请注意,“标记”是非常重要的概念)
    • while(在\ Dstates\ 中有一个未标记的状态\ T) \lbrace \\ \quad \quad \ 给T加上标记; \\ \quad \quad \ for(每个输入符号a) \lbrace \\ \qquad \qquad \quad U=\epsilon-clusure\left(move(T,a) \right) \\ \qquad \qquad \quad if(U不在Dstates中) \\ \qquad \qquad \qquad \qquad \, 将U加入Dstates中,且不加标记; \\ \qquad \qquad \quad Dtran[T,a]=U \\ \quad \quad \ \rbrace \\ \rbrace

解释一下:这部分代码和虎书上的代码意思相近,这个更好理解。算法里的Dtran[T,a]=\epsilon-clusure\left(move(T,a) \right)每个Dtran[T,a]都可能是DFA的一个状态。

2 举个例子解释

  • 题目:给定一个正则表达式(a|b)^*abbNFA,我们使用子集构造法构造DFA
    NFA
  • 解法:首先,我们分析得出,NFA的初始为状态0。因而初始状态集A=\epsilon-closure(0)=\lbrace0,1,2,4,7 \rbrace
    1. A被加上标记,对于输入符号a,b,分别求出:
      a:B=\epsilon-closure(move(A,a))=\lbrace1,2,3,4,6,7,8 \rbrace \\b:C=\epsilon-closure(move(A,b))=\lbrace1,2,4,5,6,7 \rbrace
    2. B,C都没有被标记,因而将B,C依次加上标记,对于输入符号a,b,分别求出:
      a:B=\epsilon-closure(move(B,a))=\lbrace1,2,3,4,6,7,8 \rbrace \\b:D=\epsilon-closure(move(B,b))=\lbrace1,2,4,5,6,7,9 \rbrace
      a:B=\epsilon-closure(move(C,a))=\lbrace1,2,3,4,6,7,8 \rbrace \\b:C=\epsilon-closure(move(C,b))=\lbrace1,2,4,5,6,7 \rbrace
    3. 现在只剩D没有加标记,因而给D加上标记,对于输入符号a,b,分别求出:
      a:B=\epsilon-closure(move(D,a))=\lbrace1,2,3,4,6,7,8 \rbrace \\b:E=\epsilon-closure(move(D,b))=\lbrace1,2,4,5,6,7,10 \rbrace
    4. 还剩一个E没有标记,因而给E加上标记,对于输入符号a,b,分别求出:
      a:B=\epsilon-closure(move(E,a))=\lbrace1,2,3,4,6,7,8 \rbrace \\b:C=\epsilon-closure(move(E,b))=\lbrace1,2,4,5,6,7 \rbrace
    5. 所有构造出来的集合都已经被标记,构造完成!A,B,C,D,E为五个不同状态:
      A=\lbrace0,1,2,4,7 \rbrace \\ B=\lbrace1,2,3,4,6,7,8 \rbrace \\ C=\lbrace1,2,4,5,6,7 \rbrace \\ D=\lbrace1,2,4,5,6,7,9 \rbrace \\ E=\lbrace1,2,4,5,6,7,10 \rbrace
    6. 接着就是根据状态来画图了,最好先画好状态表:


      子集构造状态表

解释一下:由此可知,A通过a,连到B,以此类推。就可以做出DFA图了^_^

转换后的DFA状态图

3 如何最小化DFA的状态数量

很简单,如果开始于s_1的机器接收字符串\sigma,始于s_2的和始于与s_1接收的串相同并到达相同状态,且两个状态集同为终态或者非终态,那么s_1,s_2是等价的。我们可以把指向s_2的连线全部指向s_1,并删除s_2,反之亦然。

  • 举个书上的例子:


    书上的NFA转DFA示例图
  • 图中的\lbrace 5,6,8,15 \rbrace,\lbrace 6,7,8 \rbrace是等价的,还有\lbrace 10,11,13,15 \rbrace,\lbrace 11,12,13 \rbrace也是等价的。

Tips:在判断是否等价前,我们要先判断是否为死状态哦(1.不能到达终态 2.从开始没有路径指向这个状态)。

4 总结

NFADFA知识总结就到这里,有什么问题请留言,有错误请批评指正,非常感谢您的阅读。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269