状态集 Q 是 {q0, q1, q2, q3, q4}。您的等效 DFA 的状态将从 NFA 的所有状态子集的集合中提取,其中有 2^5 = 32。其中一些可能无法到达,因此我们只能介绍我们实际到达的那些。
DFA 中的初始状态将是 NFA 的状态子集,其中包含 q0 以及通过仅遍历 epsilon/lambda 转换可从 q0 到达的任何状态。在这里,DFA 的初始状态是 {q0,q1},因为 q0 是 NFA 的初始状态,并且 q1 可以从 q0 通过仅遍历(恰好一个)epsilon/lambda 转换到达。
现在我们需要为字母表中的每个符号离开状态 {q0,q1} 的转换:a 和 b。在输入 a 时 {q0,q1} 转换到的状态是所有状态的子集,其中仅包含 NFA 中通过恰好消耗一个 a 并遍历任意多个 epsilon/lambda 转换可从 q0 或 q1 到达的状态。如果已经在 q0 中,符号 a 会导致 NFA 转换到 q0,并且 q1 可以通过遍历 epsilon/lambda 转换从 q0 到达;所以 q0 和 q1 将在下一个状态对应的子集中。因为在 NFA 中 q1 不会在 a 上转换,所以此状态不会添加任何内容:{q0,q1} 在输入 a 上转换为 {q0,q1}。在输入 b 上,q0 转换到自身和 NFA 中的 q2(以及 q1,因为 q1 可以通过 epsilon/lambda 转换从 q0 到达)。在 NFA 中,q1 转换为 NFA 中的 q4 和 q2,因此这些状态也在我们的状态对应的子集中。因此,{q0,q1} 在输入 b 上转换为 {q0,q1,q2,q4}。
我们遇到的唯一缺少转换的状态是 {q0,q1,q2,q4}。在输入 b 上,我们能够从另一个状态到达这些状态中的每一个(q1 通过在从 q0 转换到 q0 后进行 epsilon/lambda 转换);但无法达到 q3。因此,{q0,q1,q2,q4} 在输入 b 上转换为自身。在输入 a 上,我们可以从 q0 到达 q0(因此 q1); q1 没有;和来自 q2 或 q4 的 q3(因此 q4 通过 epsilon/lambda 转换)。因此,{q0,q1,q2,q4} 在输入 a 上转换为 {q0,q1,q3,q4}。
我们遇到的唯一缺少转换的状态是 {q0,q1,q3,q4}。在输入 a 上,验证我们是否达到相同的状态 {q0,q1,q3,q4}。在输入 b 上,验证我们是否达到状态 {q0,q1,q2,q4}。
没有我们缺少转换的状态。我们现在可以枚举状态,给它们更短的名字:{q0,q1} 是 A; {q0,q1,q2,q4} 是 B; {q0,q1,q3,q4} 是 C。现在,转换表如下:
Q | s | Q'
===|===|===
A a A
A b B
B a C
B b B
C a C
C b B
接受状态将是我们的任何状态,它们对应于包含在 NFA 中接受的 NFA 状态的子集:q3 或 q4。状态 B 和 C 都包含状态 q4,在 NFA 中是接受的;所以B和C都接受了。语言是所有至少包含一个 b 的字符串的语言。要确定这是正确的语言,请考虑 NFA。
- 任何至少有一个 b 的字符串都必须最后一次出现 b,之后如果字符串以 b 结尾,则该字符串只包含 a(或根本不包含任何内容)。
- 到目前为止,任何字符串都可以通过在 NFA 中的状态 q0 上循环来消耗
- 然后,可以将 epsilon/lambda 转换带到 q1
- 然后,可以消耗字符串中的最后一个 b 以转换到 q4
- 从那时起,所有剩余的 a(如果有的话)都可以消耗掉
- 必须消耗至少一个 b 才能从 q1 到达 q4 或到达 q2 才能到达 q3。
此 DFA 不是最小的,此语言有两个状态的 DFA:
Q | s | Q'
===|===|===
X | a | X
X | b | Y
Y | a | Y
Y | b | Y
如果 X 是初始状态,Y 是接受状态,则它接受相同的语言。