问题:
定义一个接受{0,1}上所有字符串的DFA,这样五个连续位置的每个块至少包含两个0。请仔细阅读问题。问自己:这是否允许e(epsilon(空字符串))被接受? 0101怎么样?这些英文描述可以在各种书籍中找到,我想确保你知道如何阅读和解释。
讲师提示:""" 5"可以通过编程方式生成DFA而不会有太多麻烦。我做了两种方式(手动和编程)。因为我对Emacs和键盘宏很好,所以我甚至可以手工制作'机械地,非常快。但程序化不易出错且紧凑。"
我把这件事画了出来,我觉得我做错了,因为它失控了。
我在python中制作之前的DFA草图:
然而,这是不对的,因为索引2,3,4,5和6构成了五个连续位置的块,所以我需要考虑至少两个零。哦,很好,我一直认为它需要两个1,而不是两个0。我是以完全错误的方式来做这件事的吗?因为我思考的方式,这将有大量的州。
(回到绘制这个大型DFA)
答案 0 :(得分:2)
我将这样做的方法是为每个可能的5位字符串定义一个状态,表示最后看到的5位。从表示00000的状态开始,自然地从状态移动到状态,并用2个或更多的零标记每个状态作为接受。
答案 1 :(得分:1)
我将这样做的方法是为每个可能的5位字符串定义一个状态,表示最后看到的5位。从表示00000的状态开始,自然地从状态移动到状态,并用超过2个零标记每个状态作为接受。
答案 2 :(得分:1)
如果你想以旧学校的方式做到这一点:
def check(s):
buffer = s[:5]
i = 5
count0, count1 = 0, 0
while i < len(s):
if len(buffer) == 5:
first = buffer[0]
if first == '0':
count0 -= 1
else:
count1 -= 1
buffer = buffer[1:]
buffer += s[i]
if buffer[-1] == '0':
count0 += 1
else:
count1 += 1
if count0 < 2:
return "REJECT"
i += 1
if buffer.count('0') >= 2:
return "ACCEPT"
else:
return "REJECT"
一种稍微聪明的方式:
def check(s):
return all(ss.count('0')>=2 for ss in (s[i:i+5] for i in xrange(len(s)-4)))
上述方法的详细代码:
def check(s):
subs = (s[i:i+5] for i in xrange(len(s)-4))
for sub in subs:
if sub.count('0') < 2:
return "REJECT"
return "ACCEPT"
尚未测试此代码,但它应该可行。你的教授可能想要第三种方法。
希望这有帮助
答案 3 :(得分:1)
实际上有 11 16个州,包括单一拒绝状态。状态对应于最多四个字符的历史记录,在第二个最近的零点处被截断。只需要四个字符,因为转换构成了块中的第五个字符;如果转换字符不是0并且四字符历史记录中没有两个零,则转换将失败。
我手动生成了转换,因为它的输入速度比编写Python要快,所以我会将广义(k,n)(n个块中的k个零)问题作为编码练习。 (我将x插入状态名称以使其排列更好。)
sxx00 (0)->sxx00 (1)->sx001
sx001 (0)->sx010 (1)->s0011
sx010 (0)->sxx00 (1)->s0101
s0011 (0)->s0110 (1)->s0111
s0101 (0)->sx010 (1)->s1011
s0110 (0)->sxx00 (1)->s1101
s0111 (0)->s1110 (1)->sFAIL
s1011 (0)->s0110 (1)->sFAIL
s1101 (0)->sx010 (1)->sFAIL
s1110 (0)->sxx00 (1)->sFAIL
sFAIL (0)->sFAIL (1)->sFAIL
[编辑]:这实际上并不完全正确,因为(当我读到这个问题时),应该接受字符串'1111'。 (由于没有五个字符的块,所以每个五个字符的块都有两个零,因为没有五个字符的块。)所以还有一些额外的启动状态:
start (0)->sxx00 (1)->s1
s1 (0)->sx010 (1)->s11
s11 (0)->s0110 (1)->s111
s111 (0)->s1110 (1)->s1111
s1111 (0)->sFAIL (1)->sFAIL
最后一个看起来很像sFAIL的状态是不同的,因为它是一个接受状态。