其实很简单。每次读取“ab”时,都会在堆栈中存储一个标记。然后在阅读“c”之后,您从该令牌中取出一个。然后对于每个“bb”,您从堆栈中取出一个标记。当堆栈为空时,您接受。
对于 NPDA 本身,这取决于您如何定义接受度。根据您的问题,我不明白“写一个a,然后向右移动”是什么意思。您是否将 NPDA 与图灵机混淆了? NPDA 与 NFA(非确定性有限自动机)非常相似,只是它配备了一个堆栈,您可以在其中放置堆栈符号。在此处阅读更多信息:http://www.cs.duke.edu/~rodger/courses/cps140/lects/sectnpdaH.pdf
下面是转换表,假设堆栈符号{A,Z} 其中Z 是初始堆栈符号。当我们处于唯一的接受状态 qa 并且我们已经完成读取输入磁带时接受。假设每次转换总是消耗一个堆栈符号,如果在 NPDA 不处于接受状态时没有更多符号要消耗,则 NPDA 不会接受(或拒绝)该字符串。
在下表中,第一列代表我们当前所处的状态以及我们正在读取的堆栈符号。随后的列表示在读取输入字符串中的特定字符(或根本不使用 ε 读取任何字符)时推入堆栈的新状态和堆栈符号
+--------++---------+--------+--------+--------+
| ||一个 |乙 | c | ε |
+--------++---------+--------+--------+--------+
|(q
1,Z)|| (q
2,Z) | - | - | - |
+--------++---------+--------+--------+--------+
|(q
1,A)|| (q
2,A) | - | (q
3,ε) | - |
+--------++---------+--------+--------+--------+
|(q
2,Z)|| - |(q
1,ZA) | - | - |
+--------++---------+--------+--------+--------+
|(q
2,A)|| - |(q
1,AA) | - | - |
+--------++---------+--------+--------+--------+
|(q
3,Z)|| - | - | - |(q
a,ε) |
+--------++---------+--------+--------+--------+
|(q
3,A)|| - | (q
4,A) | - | - |
+--------++---------+--------+--------+--------+
|(q
4,A)|| - | (q
3,ε) | - | - |
+--------++---------+--------+--------+--------+
这里的关键思想是堆栈中 A 的数量表示短语“ab”在输入字符串中出现的次数。
您可以看到,在使用堆栈符号 Z 读取状态 q1 中的“a”时,我们将 Z 推回堆栈。这意味着仍然没有检测到“ab”。然后它将转到 q2。
在 q2 中,我们只接受“b”,任何其他输入都会导致它挂起(并因此拒绝)。它将读取的状态推回堆栈,加上一个额外的 A,有效地将堆栈中的 A 数量增加 1,因为此转换表示输入字符串中的附加短语“ab”。
状态q3表示成功读取“c”后的部分。请注意,从 q1 到 q3 的转换必须消耗 A,而不是 Z,因为我们有约束 n >= 1。然后,在读取“b”后,它将进入状态 q4 以等待另一个“b”。稍后 q4,在读取“b”时,会消耗堆栈符号 A,匹配
在状态 q3,一旦我们到达堆栈符号 Z,我们还希望转换到接受状态 qa,指的是有 n 副本的状态"ab" 和 n-1 "bb" 的副本。
State q4 只接受带有堆栈符号A的输入字符串“b”,表示找到一个新短语“bb”应该匹配之前找到的一个短语“ab”。
希望这会有所帮助!