Sipser CH2 PROBLEMS'ANSWER 6-10
2.23
NPDA 非决定性地猜测一个位置
,并认定 和 在该位置的字符不同( )。 执行逻辑:
- 自动机读取
的前 个字符,但不使用栈。 - 读取第
个字符 ,并利用有限状态(例如,转移到“记忆0”或“记忆1”等特定状态)将其“记忆”下来。 - 读取
的后缀( 之后的所有字符),每读一个字符就向栈中推入一个标记。 - 读取 # ,然后读取 的前
个字符,同样不使用栈。 - 读取
的第 个字符 ,并与状态中记忆的 比较。如果两者相同,则此路不通;如果不同,则继续。 - 读取
的后缀,每读一个字符就从栈中弹出一个标记。
- 自动机读取
如果输入结束时栈正好变空,说明
和 的前后缀长度均对应相等,总长度也相等,且在位置 存在不匹配。因此,字符串被受理。 所以,
是上下文无关语言。
2.24
问题
证明语言
解答
要证明语言
构造一个接受该语言的下推自动机 (Pushdown Automaton, PDA)。
构造一个生成该语言的上下文无关文法 (Context-Free Grammar, CFG)。
一个更简洁的策略是,将语言
步骤 1: 分解语言 E
语言
我们可以将这个复合条件分解。
条件
条件
因此,一个字符串
并且 并且 并且 并且
现在我们来分析这些条件:
对于条件 1: 如果
,那么 。对于所有 ,都有 。因此, 必然意味着 。所以这个条件可以简化为 。 对于条件 2: 如果
,那么 。所以条件 不可能成立。这个情况对应的语言是空集。 对于条件 4: 如果
,那么 。这自然意味着 。所以这个条件可以简化为 。 对于条件 3:
并且 。这个条件不能再简化,它等价于 。
综上所述,语言
因此,
步骤 2: 证明每个子语言都是上下文无关的
现在我们只需要证明
1. 证明
我们可以为
包含以下产生式: 是开始符号。
产生式
产生式
2. 证明
我们可以为
包含以下产生式: 是开始符号。
产生式
3. 证明
对于
我们可以构造一个 NPDA,其工作原理如下:
- 当读入字符串的
部分时,对于每一个读入的 ,NPDA 非确定性地选择执行以下两个操作之一: - 将一个符号(例如
)压入堆栈。 - 将两个符号(例如
)压入堆Stack。
- 将一个符号(例如
- 当读完所有的
个 后,堆栈中将包含 个 ,其中 。这是因为要满足最终条件,NPDA 必须至少有一次选择压入一个 ,也必须至少有一次选择压入两个 。(我们可以通过状态转换来强制这一点)。 - 当开始读入字符串的
部分时,每读入一个 ,就从堆栈中弹出一个 。 - 如果在读完所有
的那一刻,堆栈也刚好变空,那么该字符串被接受。
这个 NPDA 能够接受的字符串
步骤 3: 结论
我们已经将语言
由于上下文无关语言类在并集运算下是封闭的,所以这三个上下文无关语言的并集也必然是上下文无关语言。
因此,语言
2.25
问题陈述
对于任意语言
证明思路
为了证明上下文无关语言类在某个运算下是封闭的,我们通常采用构造性证明。也就是说,如果我们有一个上下文无关语言
证明一个语言是上下文无关的,主要有两种方法: 1. 为其构造一个上下文无关文法(Context-Free Grammar, CFG)。 2. 为其构造一个下推自动机(Pushdown Automaton, PDA)。
这里,我们使用第一种方法,即通过改造语言
证明过程
假设
第一步:处理空串
首先,我们可以简化问题,先考虑不包含空串
- 如果
,那么 。 - 如果
,那么 。
由于 CFL 类在并集运算下是封闭的,而
因此,我们只需证明对于任意不含
第二步:文法规范化
对于任何不含
(其中 是非终结符) (其中 是终结符)
第三步:构造新的文法
基于
:用于生成与原先 完全相同的字符串集合。 :用于生成由 所生成的任意字符串的所有后缀。
下面是
非终结符集合
: 终结符集合
: (终结符不变) 起始符号
: (因为我们的目标是生成 中字符串的后缀) 产生式集合
: 中的产生式根据 中的规则生成,规则如下: - 对于
中形如 的规则: 一个由 生成的字符串就是 。它的后缀是 和 。因此,我们向 中添加以下规则: - 对于
中形如 的规则: 一个由 生成的字符串 是由一个来自 的字符串 和一个来自 的字符串 连接而成,即 。 的后缀有两种可能: - 它完全是
的一个后缀。 - 它包含了整个
,前面还跟了 的一个后缀。
中添加以下规则: (生成完整的字符串) (对应情况1,只生成 的后缀) (对应情况2,生成 的后缀拼接上完整的 )
- 它完全是
- 对于
第四步:证明构造的正确性
我们需要证明我们构造的文法
(a)
通过观察构造过程,我们可以发现所有带有 full
下标的非终结符的产生式都与原 G 中的产生式一一对应。
(b)
- 证明
假设
- 基础情况: 推导为一步
。此时 。后缀 只能是 或 。根据我们的构造, 中有规则 和 。所以 。 - 归纳步骤: 假设推导的第一步是
,所以 。字符串 可以被分解为 ,其中 且 。 - 情况 i:
之间的分割点在 内部。即 且 ,其中 。这意味着 。根据归纳假设, 。由于 中有规则 ,所以 ,因此 。 - 情况 ii:
之间的分割点在 内部或边界上。即 ,其中 。这意味着 并且 。根据归纳假设, 。又因为 ,所以 。 中有规则 ,所以 。因此 。
- 情况 i:
- 证明
假设
- 基础情况: 推导为一步
或 。这要求原语法 中必须有规则 。 和 都是 的后缀,而 。所以 。 - 归纳步骤: 假设推导的第一步是
。 - 情况 i: 规则是
(原规则为 )。 。根据归纳假设, ,即存在 使得 。因为 是 中的规则,我们可以任取一个 ,然后得到 。令 ,则 。因此 。 - 情况 ii: 规则是
(原规则为 )。 可以被分解为 ,其中 且 。根据归纳假设, 且 。 意味着存在 使得 。由于 是 中的规则,那么 。这个字符串可以写成 。因此 。
- 情况 i: 规则是
综上所述,我们证明了
结论
我们已经成功地为任意一个上下文无关语言
因此,上下文无关语言类在
2.26
陈述
证明:如果 G 是一个 Chomsky 范式 (CNF) 的上下文无关文法
(CFG),那么对于 L(G) 中任意长度为
证明
1. 回顾 Chomsky 范式 (CNF) 的定义
一个上下文无关文法 G 如果是 Chomsky 范式,那么它的所有产生式规则都必须是以下两种形式之一:
(其中 A, B, C 都是非终结符) (其中 A 是非终结符, a 是终结符)
(注:对于可能产生空串
2. 分析推导过程中的规则类型和作用
一个从开始符号 S 推导出最终字符串
- 类型 1:
- 这类规则是推导过程中唯一能够产生终结符的规则。
- 最终的字符串
的长度为 ,意味着它包含 个终结符。 - 由于每应用一次类型 1
规则只会产生一个终结符,因此要生成长度为
的字符串 ,必须且正好使用 次这种类型的规则。
- 类型 2:
- 这类规则的作用是将一个非终结符替换为两个非终结符。
- 我们来观察推导过程中非终结符数量的变化:每应用一次
规则,推导式中的非终结符总数会净增加 1 (一个非终结符 A 消失,两个非终结符 B 和 C 出现)。
3. 组合分析并计算总步数
一个完整的推导从一个单一的非终结符——开始符号
S——开始。推导的最终目标是生成一个由
推导的起点:推导开始时,我们只有一个非终结符 S。
推导的终点:推导结束时,我们有一个长度为
的终结符串。 中间过程:为了从非终结符得到终结符,我们必须使用
次类型 1 ( ) 的规则。这些规则将 个非终结符分别转换为 个终结符。因此,在应用这些规则之前,推导式中必须正好有 个非终结符。 计算类型 2 规则的步数:我们的任务是从 1 个非终结符 (S) 开始,通过应用类型 2 (
) 的规则,最终得到一个含有 个非终结符的串。 - 初始状态:1 个非终结符。
- 目标状态:
个非终结符。 - 每应用一次
规则,非终结符数量增加 1。 - 因此,从 1 个非终结符变为
个非终结符,需要执行的步数是 次。 - 所以,任何推导都必须包含恰好
次类型 2 ( ) 的规则应用。
计算总步数:
- 应用类型 1 (
) 规则的步数 = - 应用类型 2 (
) 规则的步数 = - 总推导步数 = (类型 1 步数) + (类型 2 步数)
- 总推导步数 =
- 应用类型 1 (
结论
对于任何在 Chomsky 范式文法 G 中的字符串
证明完毕。
2.27
考虑字符串'if condition then if condition then a:=1 else a:=1' 容易看出有两个解析树(else匹配不同的if)
新的无模糊文法
可以定义如下:
变量集合
终端符号集合
: 起始符号:
产生式规则 R′: