编译原理:打包思维-NFA 怎么变成 DFA

像讲故事一样:NFA 怎么变成 DFA

在编译原理里,非确定有限自动机(NFA)和确定有限自动机(DFA)是两个好朋友。NFA 像个随性的向导,可以同时走多条路,而 DFA 像个严格的老师,每步只许走一条路。为了让 NFA 的"随性"变成 DFA 的"规矩",我们得学会一个"整理魔法"。别担心,这个过程没那么复杂,我们用一个简单的故事和例子,手把手带你看明白!

一、故事开场:为什么要变?

想象你在森林里跟着一个向导(NFA)找宝藏。他看到一条岔路说:"可以走左边,也可以走右边,甚至还能跳过去试试。"你得派好几个分身去试每条路,看哪个能到宝藏。这很灵活,但太乱了。如果能把这些乱七八糟的路线整理成一张简单地图(DFA),上面写着"看到这个就去那儿",找宝藏就轻松多了。

在计算机里,NFA 是从正则表达式来的,很容易做出来,但它"分身太多"不好用。DFA 每步只有一条路,电脑喜欢,所以我们要把 NFA 变成 DFA。

二、主角登场:一个简单的 NFA

我们用一个简单的例子:识别"以 a 开头,后面跟任意多个 b"(正则表达式 ab*)。它的 NFA 长这样:

  • 有三个点:起点 q0,中间点 q1,宝藏点 q2
  • 路线:
    • q0 看到 a 可以去 q1
    • q1 看到 b 可以回到 q1(循环)。
    • q1 啥也不看(空跳)也能到 q2
  • 起点是 q0,宝藏在 q2

这个 NFA 很随性:读到 b 时可以循环,可以跳,挺自由的。

三、整理思路:从乱到整齐

要把 NFA 变成 DFA,我们得解决它的"随性"。NFA 的问题是:一个点读一个字母,可能去好几个地方,还能空跳。我们要做的,就是把所有"可能去的地方"打包成一个大点,让每步只有一条路。

比喻:

  • NFA 像个向导说:"读到 a,你可以去这儿那儿。"
  • DFA 像个老师说:"读到 a,你就去这个大包裹,里面装了所有可能的地方。"

这个"打包"的过程,就是把 NFA 的多个可能性合起来,变成 DFA 的一个状态。

四、动手整理:一步步来

我们拿 ab* 的 NFA 来试试,假装自己在画新地图。

第一步:从起点开始

  • NFA 起点是 q0。问:"从 q0 能空跳到哪儿?" 答案是没有空跳,所以 DFA 的起点就是"装着 q0 的包裹",记作 {q0}

第二步:读字母,看去哪儿

  • {q0}a
    • NFA 说:q0 --a--> q1
    • q1 能空跳到 q2q1 --ε--> q2)。
    • 所以,把所有能到的地方打包:{q1, q2}
    • 新地图写:{q0} --a--> {q1, q2}
  • {q0}b
    • NFA 说:q0 没路。
    • 所以没新地方,暂时不管。

第三步:从新包裹继续

  • 现在有了 {q1, q2},从它读 b
    • q1 --b--> q1q2 没路。
    • q1 还能空跳到 q2
    • 打包:还是 {q1, q2}
    • 新地图写:{q1, q2} --b--> {q1, q2}(自己到自己)。
  • {q1, q2}a
    • q1q2 都没路。
    • 所以没新地方。

第四步:定下宝藏

  • NFA 的宝藏在 q2
  • DFA 只要包裹里有 q2,就是宝藏点。
  • {q1, q2}q2,所以它是宝藏点。

新地图(DFA):

  • 两个点:{q0}{q1, q2}
  • 路线:
    • {q0} --a--> {q1, q2}
    • {q1, q2} --b--> {q1, q2}
  • 起点:{q0}
  • 宝藏:{q1, q2}

五、试试看:新地图好用吗?

  • 输入 a:从 {q0} --a--> {q1, q2},到宝藏,成功!
  • 输入 ab{q0} --a--> {q1, q2} --b--> {q1, q2},还是宝藏,成功!
  • 输入 b:从 {q0} 没路,失败。

跟 NFA 一样能认出 ab* 的东西,但每步只有一条路,简单多了!

六、整理的秘密:打包和空跳

这个"魔法"的关键是两点:

  1. 打包:把 NFA 所有可能的状态装进一个包裹,变成 DFA 的一个点。
  2. 空跳 :每次算新包裹时,别忘了 NFA 的空跳(像 q1 --ε--> q2),得把能跳到的地方也装进去。

这个过程就像把向导的口头建议整理成一张表格,告诉你在哪儿读到什么就去哪儿。

七、为什么这么做?

在编译器里,NFA 是从正则表达式来的,但它太"随性",电脑跑起来得试所有分身,太慢。DFA 每步只有一条路,电脑一看就知道下一步,很快。所以我们用这个方法,把 NFA 变成 DFA,让词法分析又快又准。

八、总结:从故事到领悟

NFA 像个随性的向导,DFA 像个严格的老师。把 NFA 变成 DFA,就是把所有"可能"打包成"一定",从乱七八糟的路线变成一张简单地图。用 ab* 的例子,我们一步步整理,看到它怎么从三个点变成两个包裹,每步都清清楚楚。

下次再看到代码被编译器读懂时,想想这个小故事:从随性到规矩的魔法,就藏在里面!

相关推荐
Asthenia041229 分钟前
RBAC模块分析:菜单-权限/角色-权限/用户-角色
后端
uhakadotcom44 分钟前
MQTT入门:轻量级物联网通信协议
后端·面试·github
ONE_Gua1 小时前
chromium魔改——navigator.webdriver 检测
前端·后端·爬虫
可乐加.糖2 小时前
一篇关于Netty相关的梳理总结
java·后端·网络协议·netty·信息与通信
Kagol2 小时前
macOS 和 Windows 操作系统下如何安装和启动 MySQL / Redis 数据库
redis·后端·mysql
无名之逆2 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
9号达人2 小时前
java9新特性详解与实践
java·后端·面试
Aurora_NeAr2 小时前
深入理解Java虚拟机-类加载机制
后端
用户98402276679182 小时前
基于 BFF + GRPC 实现数据聚合的功能
后端·grpc
lqstyle2 小时前
序列化界的"复仇者联盟":谁才是拯救你数据的超级英雄?
后端