NFA转化DFA
2012-09-06 22:51
337 查看
NFA转化DFA
NFA既然和DFA等价,那么,它们之间就存在对应关系,DFA到NFA的转化是自明的:没有空转移,把返回的单个state编程仅包含一个state的集合,就是一个形式上的NFA。但是,NFA到DFA的转化就不是那么简单了,实际上,在计算理论中,它属于ExpSpace问题,是一类比NP问题更难的问题。往简单了说,因为NFA的转移函数的返回值是个state集合,如果NFA的state数目为n,那么这个state集合的集合,就是整数[0,n)的幂集,这个幂集的元素数目是 2^n ,不错,在最坏情况下,包含n个状态的NFA对应的DFA有 2^n 个状态。虽然这个 让人很悲观,但是在实际情况中,大部分(除了那些精心构造的)NFA对应的DFA远远小于 2^n,并且往往只是O(n)。
具体的转化算法,叫做“子集构造法”,其实翻译成“幂集构造法”应该更合适。在实现该算法的过程中,有两点值得注意:
l ε闭包,在把一个新的NFA状态加入子集时,不是只要加入这个NFA状态,而是要加入该状态的整个ε闭包(需要用DFS或者BFS去计算)
l 对每个NFA状态子集按状态号排序,得到一个有序数组,再去重,然后把该数组作为Key,创建一个子集的集合(set of subset),即幂集(power set)
我实现该算法时,使用了adjacent difference 技术,即整个power set 是一个大数组,然后一个下标数组,每个下标指向一个subset的起始位置,两个下标想减即是subset的尺寸,这样内存用量更少。进一步的优化可以对subset使用差分编码(因为是有序的),即除了第一个状态号,后面的整数仅保存和前一项的差,再使用变长整数编码。
和 MinADFA_onfly一样,在这个算法的实现中用到了gold_hash_tab,不过这里对对gold_hash_map的使用非常trick,但的确同时优化了memory和speed!有兴趣的可以看一下代码。
相关文章推荐
- NFA到DFA的转化
- 词法分析(4)---NFA与DFA的转化
- 编译原理实验——将NFA转化为DFA
- <编译原理>NFA转化DFA 及 DFA的化简
- NFA转化DFA
- 词法分析(4)---NFA与DFA的转化
- NFA构造及NFA转化为DFA
- DFA与NFA
- 编译原理中的正则表达式、NFA和DFA
- 【直接NFA->DFA】易错点
- 【编译原理】:NFA转变为DFA的子集构造法
- 编译器技术简析(一)- Lexical Analysis之NFA-DFA
- DFA与NFA
- NFA-DFA(c++实现代码c#实现画图)
- 编译原理(二) NFA的确定化及DFA的最小化的算法及C++实现
- DFA&NFA
- NFA 与 DFA 的转换
- 学习笔记:NFA, DFA和Regex
- 利用子集构造法实现NFA到DFA的转换
- DFA&NFA(简易比较)