【程序语言与编译】NFA转DFA(子集构造法)

适合读者:软考中级备考同学

阅读时间:4分钟

内容:子集构造法原理、算法步骤、示例、例题


1. 为什么需要NFA转DFA?

NFA(非确定有限自动机)构造直观,但直接模拟运行效率较低(需要回溯或并行跟踪多个状态)。DFA(确定有限自动机)每个输入符号唯一确定下一状态,模拟运行速度快,更易于硬件实现或编程。

理论 :NFA和DFA的识别能力等价------任何NFA都可以转换为等价的DFA。转换的标准算法称为子集构造法(Subset Construction)。

软考中常考查子集构造法的基本思想或简单实例的转换。


2. 核心概念:ε-闭包

在NFA中,允许不读入任何输入符号(ε)就转移状态。转换前需要先理解ε-闭包

  • ε-闭包 (ε-closure):从某个状态出发,通过0条或多条ε转移所能到达的所有状态的集合。
  • 例如:状态A有ε边到B,B有ε边到C,则 ε-closure({A}) = {A, B, C}。

3. 子集构造法算法步骤

目标:构造一个DFA,使得它接受的字符串集合与原NFA完全相同。

  1. 初始化

    • 计算NFA初始状态的ε-闭包,记为 S0。这个 S0 就是DFA的初始状态。
    • S0 加入未处理队列,并作为DFA的一个状态。
  2. 对每个未处理的DFA状态(即NFA状态子集),处理所有输入符号

    假设当前DFA状态为 T(T 是一个 NFA 状态子集)。对于每个输入符号 a(通常来自字母表 Σ):

    • 计算 move(T, a):从 T 中任一状态出发,读入一个 a 所能到达的所有NFA状态的集合。
    • 计算 ε-closure(move(T, a)),得到一个新的NFA状态子集 U
    • 如果 U 不为空,且尚未在DFA中出现过,则将 U 作为一个新的DFA状态加入队列。
    • 记录DFA中从 TU 在输入 a 下的转移。
  3. 标记终止状态

    如果DFA的某个状态(即NFA状态子集)中包含NFA的至少一个终止状态,那么该DFA状态为终止状态。

  4. 重复直到所有状态都处理完毕。


4. 示例:NFA转DFA

4.1 原NFA描述

  • 状态:A(初始),B,C(终止)。
  • ε转移:无。
  • 转移:
    • A 读 0 → A 和 B
    • A 读 1 → A
    • B 读 1 → C
  • 其他转移无。

这个NFA识别所有以 01 结尾的串。

4.2 转换过程

第1步:初始状态 ε-closure({A}) = {A}(无ε转移)。记为 D_A = {A}。

第2步:处理 D_A = {A}:

  • 输入 0:move({A},0) = {A, B},ε-closure({A,B}) = {A, B} → 新状态 D_{AB} = {A, B}
  • 输入 1:move({A},1) = {A},ε-closure({A}) = {A} → 已存在 D_A

第3步:处理 D_{AB} = {A, B}:

  • 输入 0:move({A,B},0) = {A, B}(A→A,B;B无0),闭包 {A,B} → 已有 D_{AB}
  • 输入 1:move({A,B},1) = {A, C}(A→A;B→C),闭包 {A, C} → 新状态 D_{AC} = {A, C}

第4步:处理 D_{AC} = {A, C}:

  • 输入 0:move({A,C},0) = {A, B}(A→A,B;C无0),闭包 {A,B} → 已有 D_{AB}
  • 输入 1:move({A,C},1) = {A}(A→A;C无1),闭包 {A} → 已有 D_A

第5步:标记终止状态。原NFA的终止状态是C。在DFA状态中,D_{AC} 包含C,因此 D_{AC} 是终止状态。

4.3 得到的DFA

  • 状态:D_A(初始),D_{AB},D_{AC}(终止)
  • 转移:
    • D_A 读0 → D_{AB};读1 → D_A
    • D_{AB} 读0 → D_{AB};读1 → D_{AC}
    • D_{AC} 读0 → D_{AB};读1 → D_A

可重新命名:将 D_A 命为 q0,D_{AB} 命为 q1,D_{AC} 命为 q2。


5. 简化技巧与注意事项

  • ε闭包 是子集构造法的关键,务必先计算所有状态的ε闭包。
  • 如果NFA没有ε转移,那么每个状态子集的ε闭包就是它本身,过程会简单很多。
  • DFA的状态数在最坏情况下可能是指数级(相对于NFA状态数),但实际题目中通常很小。
  • 考试中常考的是简单NFA(2~4个状态)的转换,只需按步骤逐步推导即可。

6. 经典例题

题目1:已知NFA的转移表如下(无ε转移):

状态 输入a 输入b
0 {0,1} {0}
1 {2} {2}
2 {} {}

初始状态0,终止状态2。用子集构造法转换为DFA。

  • 初始闭包 {0} → D0
  • D0 读a:move({0},a)={0,1} → D01
  • D0 读b:move({0},b)={0} → D0
  • D01 = {0,1} 读a:{0,1}→{0,1,2}(0→0,1;1→2)→ D012
  • D01 读b:{0,1}→{0,2} → D02
  • D012 = {0,1,2} 读a:{0,1,2}→{0,1,2} → D012
  • D012 读b:{0,1,2}→{0,2} → D02
  • D02 = {0,2} 读a:{0,2}→{0,1} → D01
  • D02 读b:{0,2}→{0} → D0
  • 终止状态:包含原终止状态2的DFA状态:D012, D02。

答案:DFA有4个状态:D0(初始),D01,D012(终止),D02(终止)。


题目2 (概念):子集构造法的作用是( )。

A. 将DFA转化为NFA

B. 将NFA转化为等价的DFA

C. 最小化DFA

D. 消除ε转移

答案:B


7. 记忆口诀

NFA转DFA,子集构造法。
初态闭包起,每个符号算。
移动取闭包,新集加进来。
含终态即终态,确定化完成。


8. 给备考同学的一句话

子集构造法是软考中有限自动机部分的进阶考点。理解ε-闭包move两个操作,按步骤逐步推导,就能完成转换。考试中一般不会要求处理过于复杂的NFA,掌握教材上的简单例子即可。如果遇到选择题,记住"子集构造法"这个名字及其作用(NFA→DFA)就能得分。


🔔 本专栏日更2篇,点击头像 → 专栏《软考中级高频考点》订阅

#软考中级 #软件设计师 #NFA转DFA #子集构造法 #有限自动机

相关推荐
半只小闲鱼1 小时前
合并多个excel文件到一个文件中
前端·python·数据分析
咸甜适中1 小时前
rust语言学习笔记Trait(十七)Send、Sync(线程间数据所有权)
笔记·学习·rust
fobwebs1 小时前
Chrome谷歌浏览器多开教程,如何在电脑上同时登录多个GMAIL账号
前端·chrome·多开·同时登录多个gmail
前端 贾公子1 小时前
小程序蓝牙打印探索与实践 (最终章)
前端·微信小程序·小程序
chushiyunen1 小时前
vue export default
前端·javascript·vue.js
尘汐筠竹1 小时前
Day1-2 学习笔记:在 AMD 云环境上部署 Gemma 4 大模型
笔记·学习·datawhale·amdev
右耳朵猫AI1 小时前
前端周刊2026W23 | React 19.2.7、Conductor重写提速、Lovable切换TanStack Start
前端·react.js·前端框架
逸模2 小时前
逸模 VS CAD+SU系列(三)工程量---逸模模型级智能算量,数据同源闭环 助力公装项目精准控本高效拓店
人工智能·笔记·算量·公装·构件库
zhangrelay2 小时前
个体智能大模型使用的主观数据复盘-节选-2026-
笔记·学习·课程设计