【发布时间】:2017-10-09 19:44:30
【问题描述】:
我正在尝试在字母 {a,b,c} 上构建一个 DFA,以接受具有三个连续相等字母的所有字符串的集合。
例如它可以接受:aaa, bbb, ccc, abbb, caaac, ccbbbcc, aaabbbc..
我尝试了不同的方法,但它变成了一个巨大的图表我想知道是否有更优雅的方法来做这个?
【问题讨论】:
标签: computer-science automata finite-automata nfa
我正在尝试在字母 {a,b,c} 上构建一个 DFA,以接受具有三个连续相等字母的所有字符串的集合。
例如它可以接受:aaa, bbb, ccc, abbb, caaac, ccbbbcc, aaabbbc..
我尝试了不同的方法,但它变成了一个巨大的图表我想知道是否有更优雅的方法来做这个?
【问题讨论】:
标签: computer-science automata finite-automata nfa
首先,您的标题是 NFA,但您的问题正文是 DFA。我将回答这两种方式来说明为什么这很重要。
首先考虑 NFA。我们只想接受具有三个连续相同类型符号的字符串。共有三个符号,因此可以通过三种方式发生这种情况(假设我们认识到字符串将在第一次出现三个连续符号后被接受)。我们可以看到任何东西,然后是三个相同的符号,然后再次看到任何东西。 NFA 很容易写下来:
__
/ \ __
| / a,b,c / \
V / | / a,b,c
--->q0--a->q1-a->q4-a-\ V /
| \-b->q2-b->q5-b-->(q7)
\---c->q3-c->q6-c-/
我们的州执行以下操作:
在读取输入字符串的某些前缀后,NFA 不确定地分支以检查输入字符串是否包含 aaa、bbb 或 ccc,如果包含,则进入 q7 并接受可能剩余的后缀。
要获得 DFA,实际上是最小 DFA,我建议按照 Myhill-Nerode 定理进行,按字典顺序检查字符串以查看它们是否与我们已经考虑过的字符串区分开来,因此将我们的 DFA 设计为一个状态为时间。
因为我们用完了可区分的字符串,我们知道我们已经列出了最小 DFA 的所有必要状态,我们可以写下答案:
+---a--->[a]<---a----+
| +-c--->[c]<---c-+ |
| | | |
+----b--->[b]-------b------>[bb]---b----+
| |
| +---b--->[b]<---b----+ | +--+
| | +-c--->[c]<---c-+ | | | a,b,c
| | | | | V V |
--->[e]---a--->[a]-------a------>[aa]---a--->[aaa]--+
| ^
| +---a--->[a]<---a----+ |
| | +-b--->[b]<---b-+ | |
| | | | | |
+----c--->[c]-------c------>[cc]---c----+
(状态 [a]、[b] 和 [c] 分别重复两次,以使图表更漂亮。事实上,状态转换图不是平面的,渲染起来会很混乱,更不用说 ASCII 艺术了)。
请注意,这与我们写下的简单 NFA 具有相同数量的状态 - 这恰好消除了不确定性。
【讨论】: