编译原理 NFA转换为等价的DFA

713 阅读3分钟

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

定理

在有穷自动机的理论里,有这样的定理:
设L为一个由不确定的有穷自动机接受的集合,则存在一个接受L的确定的有穷自动机。

算法

介绍一种算法称为子集法,可以将NFA转换为等价的DFA

先定义状态集合I的两个运算

状态集合I的ε-闭包(ε-closure(I)):
定义为一个状态集,是状态集I中的任何状态S经过任意条ε弧而能到达的状态的集合。
显然,状态集合I中的任何元素都属于ε-closure(I)

状态集合I的a弧转换(move(I,a)):
定义为一个状态集J,其中J是所有可从I中的某一状态经过一条a弧而到达的状态的全体。

image.png

举例

image.png

  1. 初始化子集族C为空[],用表格表示
子集是否被标记
  1. 计算ε-closure(0),令 T0 = ε-closure(0) = {0,1,2,4,7},将T0加入C中,T0未被标记。
子集是否被标记
T0 = {0,1,2,4,7}0
  1. 标记T0, 令T1 = ε-closure(move(T0,a)) = {1,2,3,4,6,7,8},将T1加入C中,T1未被标记。

令T2 = ε-closure(move(T0,b)) = {1,2,4,5,6,7},将T2加入C中,T2未被标记。

子集是否被标记
T0 = {0,1,2,4,7}1
T1 = {1,2,3,4,6,7,8}0
T2 = {1,2,4,5,6,7}0
  1. 标记T1, 令T3 = ε-closure(move(T1,a)) = {1,2,3,4,6,7,8},即T1,T1已经在C中

令T3 = ε-closure(move(T1,b)) = {1,2,4,5,6,7},将T3加入C中,T3 未被标记。

子集是否被标记
T0 = {0,1,2,4,7}1
T1 = {1,2,3,4,6,7,8}1
T2 = {1,2,4,5,6,7}0
T3 = {1,2,4,5,6,7,9}0
  1. 标记T2, 令T4 = ε-closure(move(T2,a)) = {1,2,3,4,6,7,8},即T1,T1已经在C中

令T4 = ε-closure(move(T2,b)) = {1,2,4,5,6,7},即T2,T2已经在C中

子集是否被标记
T0 = {0,1,2,4,7}1
T1 = {1,2,3,4,6,7,8}1
T2 = {1,2,4,5,6,7}1
T3 = {1,2,4,5,6,7,9}0
  1. 标记T3, 令T4 = ε-closure(move(T3,a)) = {1,2,3,4,6,7,8},即T1,T1已经在C中

令T4 = ε-closure(move(T3,b)) = {1,2,4,5,6,7,10},将T4加入C中,T4 未被标记。

子集是否被标记
T0 = {0,1,2,4,7}1
T1 = {1,2,3,4,6,7,8}1
T2 = {1,2,4,5,6,7}1
T3 = {1,2,4,5,6,7,9}1
T4 = {1,2,4,5,6,7,10}0
  1. 标记T4, 令T4 = ε-closure(move(T4,a)) = {1,2,3,4,6,7,8},即T1,T1已经在C中

令T4 = ε-closure(move(T4,b)) = {1,2,4,5,6,7},即T2,T2已经在C中

子集是否被标记
T0 = {0,1,2,4,7}1
T1 = {1,2,3,4,6,7,8}1
T2 = {1,2,4,5,6,7}1
T3 = {1,2,4,5,6,7,9}1
T4 = {1,2,4,5,6,7,10}1

子集族C中所有子集都已标记,算法结束。 一共构造了5个子集

T0 = {0,1,2,4,7}
T1 = {1,2,3,4,6,7,8}
T2 = {1,2,4,5,6,7}
T3 = {1,2,4,5,6,7,9}
T4 = {1,2,4,5,6,7,10}

那么图3.6的 NFA N 构造的 DFA M 如下:

(1) S = {[T0],[T1],[T2],[T3],[T4]}

(2) ∑ = {a,b}

(3)
D([T0],a)=[T1]
D([T0],b)=[T2]
D([T1],a)=[T1]
D([T1],b)=[T3]
D([T2],a)=[T1]
D([T2],b)=[T2]
D([T3],a)=[T1]
D([T3],b)=[T4]
D([T4],a)=[T1]
D([T4],b)=[T2]

(4) S0=[T0]

(5) ST=[T4]

为便于书写,不妨将[T0],[T1],[T2],[T3],[T4]重新命名,
用0、1、2、3、4分别表示,
该 DFA M的状态转换图如图3.8所示

image.png

总结

子集法简单来说就是通过ε-closure(0)加入子集族C中的第一个子集。

对子集族C中的子集进行遍历。

对每一个未被标记的子集Ti,先标记Ti,然后对Ti的每一个输入字符i进行ε-closure(move(Ti,i))运算。

若运算产生新的子集,则将新的子集加入子集族C中。

若子集族C中的所有自己都被标记,算法结束。