ε、单字符、|(或)、连接、*(闭包) 描述一个字符串集合。优先级 * > 连接 > |。三者等价:描述同一类语言(正规语言)。正规式 → NFA → DFA 是标准流水线。
把正规式拆成 5 种基本块,每种给一小段 NFA,再拼起来[1]:
ε : →(○)─ε→(◎) 单字符a:→(○)─a→(◎) r | s :新初态 ─ε→ r 的NFA ;─ε→ s 的NFA ;两者终态 ─ε→ 新终态 r s :r 的终态 ─ε→ s 的初态(首尾相接) r * :新初态 ─ε→ r初态、─ε→ 新终态;r终态 ─ε→ r初态(循环)、─ε→ 新终态
核心思想:DFA 的一个状态 = NFA 的一组状态(子集)。两个工具函数:
① DFA 初态 = ε-closure({s0}),命名为 A。
② 对每个已得子集 T、每个输入符 a:算 U = ε-closure(move(T,a))。
③ U 若是新子集就加进来(命名 B、C…),并在转换表里登记 T --a--> U。
④ 直到没有新子集。含原 NFA 终态的子集 = DFA 终态。
(a|b)*abb 等价的 DFA。0 ─ε→ 1, 7 1 ─ε→ 2, 4 2 ─a→ 3 4 ─b→ 5 3 ─ε→ 6 5 ─ε→ 6 6 ─ε→ 1, 7 7 ─a→ 8 8 ─b→ 9 9 ─b→ 10(终)第 2 步 子集构造。初态 A = ε-closure({0}) = {0,1,2,4,7}。逐个求 ε-closure(move(·,a/b)):
| DFA状态 | = NFA 子集 | 输入 a | 输入 b |
|---|---|---|---|
| A | {0,1,2,4,7} | B | C |
| B | {1,2,3,4,6,7,8} | B | D |
| C | {1,2,4,5,6,7} | B | C |
| D | {1,2,4,5,6,7,9} | B | E |
| E(终) | {1,2,4,5,6,7,10} | B | C |
a b A ─→ B A ─→ C B ─→ B B ─→ D C ─→ B C ─→ C D ─→ B D ─→ E ★终态 E ─→ B E ─→ C
abb 这条路 A —a→ B —b→ D —b→ E(终态),✓ 被接受。下一课我们把这个 DFA 再最小化。(0|1)*01 之类的练手题。
(a|b)*abb 为龙书经典例。