DFA 的正则表达式
虽然没有从正则表达式 (RE) 绘制 DFA 的算法捷径,但通过分析而不是推导可以使用捷径技术,它可以节省您绘制最小化 dfa 的时间。但是偏离了你只能通过练习才能学习的技术。我以你的例子来展示我的方法:
(a + b)*ab
首先,考虑正则表达式的语言。如果第一次尝试很难说出语言描述是什么,那么找到可以用语言生成的最小可能字符串,然后找到第二小的......
记住一些基本正则表达式的解决方案。例如,我有written here some basic idea to writing left-linear and right-linear grammars directly from regular expression. 同样你可以写来解释最小化的 dfa。
在 RE (a + b)*ab 中,可能的最小字符串是 ab,因为使用 (a + b)* 可以生成 NULL(^) 字符串。第二小的字符串可以是aab 或bab。现在我们可以很容易地注意到关于语言的一件事是,该 RE 语言中的任何字符串总是以ab(后缀)结尾,而前缀可以是任何可能的字符串,由a 和b 组成,包括^。
另外,如果当前符号是a;那么一个可能的机会是下一个符号将是b 和字符串结尾。因此,在 dfa 中,我们需要一个转换,使得当 b 符号出现在 符号 a 之后,那么它应该移动到某些 最终状态 dfa。
接下来,如果一个新符号进入最终状态,那么我们应该移动到某个非最终状态,因为b 之后的任何符号都可能只在语言中的某个字符串中间,就像所有语言一样字符串以后缀 'ab' 结尾。
所以在这个阶段有了这些知识,我们可以绘制一个不完整的转换图,如下所示:
---►(Q0)---a---►(Q1)---b----►((Qf))
现在你需要明白:每个状态都有一些含义,例如
(Q0) 表示 = 开始状态
(Q1) 表示 = 最后一个符号是“a”,再加上一个“b”,我们可以转换到最终状态
(Qf) 表示 = 最后两个符号是 'ab'
现在想想如果符号a 进入最终状态会发生什么。更多地说明 Q1 因为这个状态意味着最后一个符号是a。 (更新转换图)
--►(Q0)---a---►(Q1)---b----►((Qf))
▲-----a--------|
但假设符号 a 不是符号 b 到达最终状态。然后我们应该从最终状态转移到某个非最终状态。在这种情况下的当前转换图中,我们应该从最终状态 Qf 移动到初始状态。(同样我们需要字符串中的ab 来接受) p>
--►(Q0)---a---►(Q1)---b----►((Qf))
▲ ▲-----a--------|
|----------------b--------|
这张图还不完整!因为来自 Q1 的符号 a 没有出边。对于状态 Q1 上的符号 a,需要自循环,因为 Q1 表示最后一个符号是 a。
a-
||
▼|
--►(Q0)---a---►(Q1)---b----►((Qf))
▲ ▲-----a--------|
|----------------b--------|
现在我相信上图中的 Q1 和 Qf 都存在所有可能的出边。一个缺失的边是符号 b 的 Q0 的出边。并且在状态 Q0 必须有一个自循环,因为我们再次需要一个 ab 序列,以便字符串可以被接受。 (ab 可以实现从 Q0 到 Qf 的转换)
b- a-
|| ||
▼| ▼|
--►(Q0)---a---►(Q1)---b----►((Qf))
▲ ▲-----a--------|
|----------------b--------|
现在 DFA 已完成!
在最初的几次尝试中,该方法可能看起来很困难。但是,如果你学会用这种方式画画,你会发现你的分析能力有所提高。你会发现这种方法是快速而客观的绘制 DFA 的方法。
* 在我给出的链接中,我描述了更多的正则表达式,我强烈建议你学习它们并尝试为这些正则表达式制作 DFA。