转自http://blog.youkuaiyun.com/lingyu940/article/details/5070137
将NFA转化为DFA
1.实验目的
输入: 非确定有限(穷)状态自动机。
输出: 确定化的有限(穷)状态自动机
2.实验原理
采用子集对NFA转DFA。
(1) 若NFA的全部初态为S1,S2,…,Sn,则令DFA的初态为:
S=[S1,S2,…,Sn],
其中方括号用来表示若干个状态构成的某一状态。
(2) 设DFA的状态集K中有一状态为[Si,Si+1,…,Sj],若对某符号a∈∑,在NFA中有F({ Si,Si+1,…,Sj },a)={ Si’,Si+1’,…,Sk’ }
则令F({ Si,Si+1,…,Sj },a)={ Si’,Si+1’,…,Sk’ }为DFA的一个转换函数。若[ Si’,Si+1’,…,Sk‘ ]不在K中,则将其作为新的状态加入到K中。
(3) 重复第2步,直到K中不再有新的状态加入为止。
(4) 上面得到的所有状态构成DFA的状态集K,转换函数构成DFA的F,DFA的字母表仍然是NFA的字母表∑。
(5) DFA中凡是含有NFA终态的状态都是DFA的终态。
还可以采用另一种操作性更强的描述方式。首先给出两个相关定义。
假设I是NFA M状态集K的一个子集(即I∈K),则定义ε-closure(I)为:
(1) 若Q∈I,则Q∈ε-closure(I);
(2) 若Q∈I,则从Q出发经过任意条ε弧而能到达的任何状态Q’,则Q’∈ε-closure(I)。
状态集ε-closure(I)称为状态I的ε闭包。
假设NFA M=(K,∑,F,S,Z),若I∈K,a∈∑,则定义Ia=ε-closure(J),其中J是所有从ε-closure(I)出发,经过一条a弧而到达的状态集。
NFA确定化的实质是以原有状态集上的子集作为DFA上的一个状态,将原状态间的转换为该子集间的转换,从而把不确定有限自动机确定化。经过确定化后,状态数可能增加,而且可能出现一些等价状态,这时就需要简化
3.实验内容
⑴ 实现计算闭包closure(I)的算法;
⑵ 实现转换函数move(q,a)的算法;
⑶ 输出NFA转DFA的结果。
DFA和NFA存储使用的数据结构为图中的邻接链表。
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置
char info; //权
struct ArcNode *nextarc; //指向下一条弧的指针
}ArcNode;
typedef struct VNode{
char data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VNode;
每个链表的第一个数据单元为N(D)FA的状态,后边的结点存储内容有指向的边和边上的权值。
例如课本图4.3的NFA M表示如下:
4.实验心得
1.一般来说,我们接触到的N(D)FA图的边数比较少,所以在选取数据结构存储时,选择邻接链表,相对于使用二维或三维数组,存储效率得到了提高。
2.在求e_closure集合时,因为是任意个空转移,因此使用深度遍历的方法,先求出一个状态的e_closure集,再用循环求出状态集的e_closure集