{0,1} Every5-Two0的确定性有限自动机

时间:2012-09-17 03:45:45

标签: python dfa

问题:

定义一个接受{0,1}上所有字符串的DFA,这样五个连续位置的每个块至少包含两个0。请仔细阅读问题。问自己:这是否允许e(epsilon(空字符串))被接受? 0101怎么样?这些英文描述可以在各种书籍中找到,我想确保你知道如何阅读和解释。

讲师提示:""" 5"可以通过编程方式生成DFA而不会有太多麻烦。我做了两种方式(手动和编程)。因为我对Emacs和键盘宏很好,所以我甚至可以手工制作'机械地,非常快。但程序化不易出错且紧凑。"


我把这件事画了出来,我觉得我做错了,因为它失控了。

我在python中制作之前的DFA草图: enter image description here

然而,这是不对的,因为索引2,3,4,5和6构成了五个连续位置的块,所以我需要考虑至少两个零。哦,很好,我一直认为它需要两个1,而不是两个0。我是以完全错误的方式来做这件事的吗?因为我思考的方式,这将有大量的州。

(回到绘制这个大型DFA)

4 个答案:

答案 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的状态是不同的,因为它是一个接受状态。