设计一种识别语言的“Push Down Automata”:a ^ n b ^ m | n <= m <= 3n

时间:2012-02-14 07:54:35

标签: pushdown-automaton automaton

我正在攻读考试自动机和正式语言,我必须设计一个识别语言的PDA:

a^n b^m | n<= m <= 3n

我有点想法,但我坚持这个:

首先想到处理所有的“a”和每个“a”推动一个“A”

(q0, a, Z)= (q0, AZ)
(q0, a, A)= (q0, AA)
(q0, b, A)= (q1, A)
(q1, b, A)= (q2, A)
(q2, b, A)= (q3, lambda)
(q3, b, A)= (q1, A)
(q3, lambda, A)= (qf, Z)
(q3, lambda, Z)= (qf, Z)

qf = final state, lambda= delete top of stack, Z= initial symbol of the stack

所以我认为解决方案,但我认为不正确,我做错了什么?

2 个答案:

答案 0 :(得分:2)

是的,你的自动机不正确,因为它不接受字符串ab,或者是空字符串。您将获得以下机器状态序列:

- q0 Z
a q0 AZ
b q1 AZ
(doesn't accept)

- q0 Z
(doesn't accept)

由于q1不接受,因此您的机器无法接受ab,这是您所描述的语言。

您有正确的一般想法:为您看到的每个a添加A,然后为您看到的每组1,2或3 b删除A.这个表述显然是不确定的,但除非要求DPDA,否则我们会认为没问题。

(q0, a, Z) => (q0, AZ)
(q0, a, A) => (q0, AA)
(q0, -, Z) => (q1, Z)
(q0, -, A) => (q1, A)

这些转换计算a并将A添加到堆栈中。当你读完一个时,我们可以进入下一个状态q1,然后开始计算b并弹出A。

(q1, -, A) => (q2, A)
(q1, -, A) => (q3, A)
(q1, -, A) => (q4, A)

这些过渡允许机器不确定地选择是否计算特定A的一个,两个或三个b。

(q2, b, A) => (q1, -)

(q3, b, A) => (q5, A)
(q5, b, A) => (q1, -)

(q4, b, A) => (q6, A)
(q6, b, A) => (q7, A)
(q7, b, A) => (q1, -)

这些转换实际上处理一个,两个或三个b的计数并移除A,返回q1以允许从堆栈中移除额外的A。

(q1, -, Z) => (qf, Z)

这种转换允许PDA在A的堆栈耗尽后接受字符串。请注意,如果输入上还有任何b,则PDA将以qf崩溃,因为那里没有定义转换;并且因为它崩溃了,所以不接受该字符串(即使堆栈为空并且它在接受状态下崩溃)。

解决此问题的另一种方法是为此语言构造CFG,然后构建自上而下或自下而上的解析器。这种语言的简易CFG是:

S := aSb | aSbb | aSbbb

如果需要DPDA,这是一个更难的问题,答案可能是“没有DPDA存在”。说实话,我没有考虑过为这种语言建立DPDA。

答案 1 :(得分:0)

我知道这有点晚了,但是我遇到了一个相同的问题,我想如果有一个不同的解决方案,那么基本的想法是你将你的堆栈分成3个具有以下属性的分区

  • 第一个分区:( size = n,character ='A')
  • 第二个分区:( size = 2n,character ='B')
  • 第三个分区:( size = n,character ='A')

最上面的分区 - 第三个分区 - 其目的是确保b的计数至少等于a的计数-n-,中间分区 - 第二个 - 是为了确保b的计数小于或者等于2n,最后一个分区是为了确保b的计数不超过2n;所以这是基本的想法,当然它是NPDA,这里是确切的过渡:

(q0 , a , #) => (q0 , A#)
(q0 , a , A) => (q0 , AA)
(q0 , a , B) => (q0 , AB)
(q0 , b , A) => (q0 , BA)
(q0 , b , B) => (q0 , BB)
(q0 , lambda , A) => (q0 , AA)
(q0 , lambda , B) => (q0 , AB)
(q0 , lambda , B) => (q0 , BB)
(q0 , lambda , A) => (q0 , BA)
(q0 , b , A) => (q1 , match) >> -match means removing the top of the stack with the current element-

现在我们转到q1以确保b的计数至少等于a的计数:

(q1 , b , A) => (q1 , match)
(q1 , # , B) => (qf , -) >> -this means that i matched equal number of a's and b's and i can halt if there is no more input-
(q1 , b , B) => (q2 , match)

现在我们转到q2以确保b的计数小于或等于2n:

(q2 , b , B) => (q2 , match)
(q2 , # , A) => (qf , -)
(q2 , # , B) => (qf , -)