我无法找到自动机,因为我只能用多个堆栈或集理论的交叉来想象它。
答案 0 :(得分:1)
语言:L = { A^i B^j C^k | 2k <= i <= 3k OR j != (i+k) }
此语言是两种语言L'
和L''
:
L' = { A^i B^j C^k | 2k <= i <= 3k }
L'' = { A^i B^j C^k | j != (i+k) }
如果我们找出每种语言的NPDA,我们可以通过以下方式为这两种语言的联合写下新的NPDA:
q*
f(q*,e,Z) = (q0',Z)
和f(q*,e,Z) = (q0'',Z)
,其中e
为epsilon / lambda,Z
是堆叠符号的底部,q0'
和q0''
是L'
和L''
的NPDA的起始状态。我们已经将更难的问题分解为两个更简单的问题,并想出如何将更简单的问题的答案放在一起来回答更难的问题。对于计算机科学,数学以及计算机程序设计等正规科学而言,这是你可能开发的最重要的技能。
L'
的NPDA应该是什么样的?它可以读取任意数量的B
,前提是它们介于A
和C
之间。我们需要跟踪我们看到的A
的数量,比如每次看到A
时将A
推到堆栈上;一旦我们开始看到C
,我们需要将A
从群集中弹出。假设我们想要通过空堆栈接受,我们需要删除所有2k = i
s;但我们怎么知道要删除多少?如果我们有A
,我们会为我们看到的每个C
删除两个i = 3k
。如果我们有A
,我们会为我们看到的每个C
删除三个A
。事实上,我们介于两者之间。这在概念上是困难的。 nondeterminism 的概念 - NPDA中的N--在这里至关重要。我们不需要确切知道字符串将如何被接受;我们只需要一个可以接受该语言中的字符串的过程,并且不能接受不在该语言中的字符串。我们可以猜测是否需要在任何特定时刻从堆栈中删除两个或三个2k
;这将保证我们不会超过3k
和Q s S Q' S'
------------------------
// read A's and push onto stack
q0 A Z q0 AZ
q0 A A q0 AA
// begin reading B's
q0 B Z q1 Z
q0 B A q1 Z
// begin reading C's if no B's
q0 C A q2 -
q0 C A q3 -
// read B's
q1 B Z q1 Z
q1 B A q1 A
// begin reading C's if B's
q1 C A q2 -
q1 C A q3 -
// pop the final A for the last C read
q2 - A q4 -
// if popping three A's, pop the middle A
q3 - A q2 -
// pop the first A for each C read after the first C
q4 C A q2 -
q4 C A q3 -
// transition to separate accepting state if stack empty
q4 - Z qA -
界限,并且它还允许我们在两者之间获得任何结果。为了使这项工作成功,我们可以简单地崩溃或拒绝所有失败的有效字符串执行,只要其中一个可能的执行通过。
这是基于此描述的NPDA,假设接受空堆栈并接受状态:
qR
在上述NPDA中,未显示导致“死”状态的转换。如果要显示它,请添加这些转换并调用状态L'
。如果没有那些明确的过渡,NPDA通常被理解为“崩溃”并拒绝输入。对于NPDA
中的任何字符串,此qA
将以状态L''
结束,并显示空堆栈。
对于另一种语言,我们可以进一步细分。 R'
是两种语言R''
和R' = { A^i B^j C^k | j < i + k }
R'' = { A^i B^j C^k | j > i + k }
的结合:
L''
使用上述相同的结构,我们可以通过查找R'
和R''
的NPD并将这些答案放在一起来为R'
创建NPDA。
对于A
,我们可以在阅读A
时将A
推入堆栈;我们可以弹出B
s,如果有的话,或者在阅读B
时推送B
;最后,我们可以弹出C
s,如果有的话,或者在阅读C
时推送j < i + k
。当且仅当我们完成时,堆栈顶部有A
或C
,我们才会A
。然后,我们可以移动到接受状态并从堆栈中弹出C
和R''
以获得空堆栈。
对于B
,我们可以做同样的事情,并在堆栈顶部寻找B
。我们可以移动到接受状态并弹出 R' R''
Q s S Q' S' Q s S Q' S'
----------------------- -----------------------
// count A's, first B/C // count A's, first B/C
q0' A Z q0' AZ q0'' A Z q0'' AZ
q0' A A q0' AA q0'' A A q0'' AA
q0' B Z q1' BZ q0'' B Z q1'' BZ
q0' B A q1' - q0'' B A q1'' -
q1' C Z q2' CZ q0'' C A q2'' CZ
q1' C A q2' CA q0'' C Z q2'' CA
// count B's, first C // count B's, first C
q1' B Z q1' BZ q1'' B Z q1'' BZ
q1' B A q1' - q1'' B A q1'' -
q1' B B q1' BB q1'' B B q1'' BB
q1' C Z q2' CZ q1'' C Z q2'' CZ
q1' C A q2' CA q1'' C A q2'' CA
q1' C B q2' CB q1'' C B q2'' CB
// count C's // count C's
q2' C Z q2' CZ q2'' C Z q2'' CZ
q2' C A q2' CA q2'' C A q2'' CA
q2' C B q2' - q2'' C B q2'' -
q2' C C q2' CC q2'' C C q2'' CC
// accept if A's or C's // accept if B's
q2' - A qA' - q2'' - B qA'- -
q2' - C qA' -
// accept if A's or C's // accept if B's
qA' - A qA' - qA'' - B qA'' -
qA' - C qA' -
以清除堆栈。
Q s S Q' S'
-----------------------
q* - Z q0 Z
q* - Z q0' Z
q* - Z q0'' Z
原始语言的NPDA如下:
qA
将前面给出的所有其他转换添加到此处,并在三个接受状态qA'
,qA''
或{{1}}中的任何一个中定义接受为空堆栈。