我知道如何弄清楚开始状态,接受状态,输入字母表以及所有这些东西。但是你如何发展PDA的过渡关系呢?对于FSM,(q0,a),q1)表示如果从q0开始并获得a,则转换为q1。但是(S,a,e),(S,a)是什么意思? (S是开始状态,e是epsilon)
答案 0 :(得分:0)
而不是(S,a,e)中的epsilon,(S,a)应该是底部符号(看起来像倒置的T)。我稍后会解释一下。
第一个S就是你现在所处的状态。这对应于FSM中的q0。
a 是您阅读的符号,与FSM中的 a 相同。请注意,当您获得 e 而不是 a 时,这意味着您位于字符串的末尾,没有什么可读的。
主要区别在于下一个字母,在本例中是 e 。这表示当您阅读 a 时,堆栈顶部的单个堆栈符号。从技术上讲,你永远不会读取空堆栈。在计算机中,这与读取空内存相同,只是无法完成。这是因为堆栈的“底部”包含一个符号,表示您位于底部。传统上,这是使用颠倒的T(底部符号)表示的。
第二个括号中的S表示您要去的状态,就像FSM中的q1一样。
最后,第二个括号中的 a 是您要添加到堆栈中的符号(或符号)。每次从堆栈中读取内容时(每次发生转换时),该符号都会从堆栈中删除。然后,您可以将新符号或几个新符号放入堆栈中,或者您可以放置任何内容(e)。当你刚刚读完底部符号时什么也不做就意味着你已经完成了,你接受了字符串(如果是空堆栈接受的话)。您也可以接受最终状态,但空堆栈更简单。
我将向您展示一个快速示例,一个用于{a ^ n b ^ n |的PDA n> = 0}。我们的字母显然是{a,b},我们需要2个状态(一个用于 a 部分,一个用于 b 部分),让我们称之为{p, q}。我们将 p 作为我们的开始状态。我们的堆栈字母表,我们可以放入堆栈的符号将是{bottom,A}。底部始终是堆栈字母表的一部分,每次我们得到 a 时我们都会将A推入堆栈(每次我们得到 b 时弹出一个) )。让我们接受空堆栈,这意味着当我们读取 e 作为符号并将 bottom 作为堆栈符号时,如果我们没有将任何内容放回堆栈,那么我们已接受该字符串。我们的delta转换如下:
(p,e,bottom),(p,e) //this is an accepting state for a^0 b^0
(p,a,bottom),(p,A bottom) //we read an a and we're at the bottom of the stack, we add an A to the stack and put back the bottom symbol below it.
(p,a,A),(p,AA) //we read an A off the stack and an *a* in our string, we put back the A we read from the stack and add another one
(p,b,A),(q,e) //we read an A off the stack and a *b*, so we go to our state q, and don't add anything to the stack.
(q,b,A),(q,e) //every time we get a *b* and there's an A on the stack, remove it
(q,e,bottom),(q,e) //this is an accepting state, as we've canceled out all the a's with b's and we're done reading our string.
请注意,有些转换是不允许的,例如在任何 a 之前获取 b 。如果不包含它们,则不接受需要它们的字符串。希望这可以帮助!