我将如何设计一个接受平衡括号和括号的 PDA,例如 ([][]),我很难开始。我需要帮助为这个问题编写转换函数。任何帮助表示赞赏
2 回答
我通常不会为他们完成某人的全部作业,但现实情况是,即使我这样做,它也不会对你有太大帮助,除非你真的了解这些东西是如何工作的,可悲的事实是,大多数学校一开始就教不好。
让我们考虑一下这个 PDA 是如何工作的,暂时忘记状态和转换等等:当我们的 PDA 获得输入时,它应该像这样工作:
- 如果没有输入:
- 如果栈顶是空的(这通常由一些特殊的值来表示
$
,比如这个例子),那么我们的 PDA 接受这个字符串:它是一个适当平衡的括号和括号字符串。 - 否则我们进入错误状态。该字符串不是正确平衡的括号和括号字符串。
- 如果栈顶是空的(这通常由一些特殊的值来表示
- 如果输入是 an
(
或 a[
,则将输入压入堆栈并查看下一个输入字符。 - 如果输入是 a
)
那么:- 如果栈顶是
(
弹出栈顶,再看下一个输入。 - 否则,进入错误状态。该字符串不是正确平衡的括号和括号字符串。
- 如果栈顶是
- 如果输入是 a
]
那么:- 如果栈顶是一个
[
弹出栈顶的状态,再看下一个输入。 - 否则,进入错误状态。该字符串不是正确平衡的括号和括号字符串。
- 如果栈顶是一个
现在,知道了我们的 PDA 必须做什么,让我们尝试考虑如何更正式地描述我们的 PDA。我们将假设:
- Τhe 组有效输入符号 Σ = {
(
,)
,[
and]
} - 初始堆栈符号 Z =
$
- Τhe 组有效堆栈符号 Γ = {
(
,[
} ∪ Z - 状态集 Q = { q0, ACCEPT, REJECT }
- 初始状态 q0。
使用类似于http://en.wikipedia.org/wiki/Pushdown_automaton上描述的符号来进行 PDA 状态转换,我们可以考虑状态以及事物如何流动:
(q0, ε, top=
$
, ACCEPT, nil)这告诉我们的 PDA:当您处于状态 q0 并且没有更多输入并且堆栈顶部$
进入 ACCEPT 状态时,堆栈保持不变。(q0, ε, top=
(
, REJECT, nil)这告诉我们的 PDA:当您处于状态 q0 并且没有更多输入并且堆栈顶部(
进入 REJECT 状态时,堆栈保持不变。(q0, ε, top=
[
, REJECT, nil)这告诉我们的 PDA:当您处于状态 q0 并且没有更多输入并且堆栈顶部[
进入 REJECT 状态时,堆栈保持不变。(q0,
(
, top=top, q0, push(
)这告诉我们的 PDA:当您处于状态 q0 并且输入是 a(
时,无论堆栈顶部是什么,进入状态 q0 并将 a 压(
入堆栈。(q0,
[
, top=top, q0, push[
)这告诉我们的 PDA:当您处于状态 q0 并且输入是 a[
时,无论堆栈顶部是什么,进入状态 q0 并将 a 压[
入堆栈。(q0,
)
, top=(
, q0, pop)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a)
并且栈顶是 a(
时,进入状态 q0,并弹出栈顶.(q0,
)
, top=[
, REJECT, nil)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a)
并且堆栈的顶部是 a 时,[
然后转到 REJECT 堆栈,保持堆栈不变。(q0,
)
, top=$
, REJECT, nil)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a)
并且堆栈的顶部是 a 时,$
然后转到 REJECT 堆栈,保持堆栈不变。(q0,
]
, top=[
, q0, pop)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a]
并且栈顶是 a[
时,进入状态 q0,并弹出栈顶.(q0,
]
, top=(
, REJECT, nil)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a]
并且堆栈的顶部是 a 时,(
然后转到 REJECT 堆栈,保持堆栈不变。(q0,
]
, top=$
, REJECT, nil)这告诉我们的 PDA:当你处于状态 q0 并且输入是 a]
并且堆栈的顶部是 a 时,$
然后转到 REJECT 堆栈,保持堆栈不变。
我们可以使用更多状态来实现这一点,但有趣的是,一个“处理”状态就足够了。
您可能还需要注意,根据您的讲师,您可能不需要明确添加 REJECT 状态,尽管这样做是一种很好的形式。
我希望这有帮助。
这可能会帮助您入门:
bool check_and_pop(char c) {
if (top() == c) {
pop();
return true;
}
return false;
}
int check_input() {
char c;
while ((c = getc())) {
switch (c) {
case '(': case '{': case '[': push(c); break;
case ')':
if (!check_and_pop('(')
return REJECT;
break;
case '}':
if (!check_and_pop('{')
return REJECT;
break;
// ...
}
// end of input, check the stack to accept/reject
if (stack_size() == 0)
return ACCEPT;
else
return REJECT;
}