1. 简介

在本教程中,我们将探讨上下文无关语言(Context-Free Languages),并重点介绍一些用于判断语言是否为上下文无关语言的技巧。


2. 什么是上下文无关语言?

要理解上下文无关语言,我们首先需要回顾一些基本概念:形式语言(Formal Language)文法(Grammar)

2.1 形式语言与文法

  • 形式语言 是由一组符号组成的字符串集合,这些符号来自一个非空的字母表(Alphabet)。

    • 例如:语言 L_1 = \{a^k b^k \mid k = 0,1,2,\ldots\} 是由字母表 \{a, b\} 构成的语言。
  • 文法 描述了如何生成语言中的字符串。形式上,文法是一个四元组:(V, \Sigma, S, P),其中:

    • V:所有符号的集合
    • \Sigma:字母表(即终结符)
    • V \setminus \Sigma:非终结符(变量)
    • S:起始符号
    • P:产生式规则集合

例如,以下规则可以生成语言 L_1 = \{ a^k b^k \mid k\geq 0 \}

(1)  
S → aSb  
S → ε

其中 ε 表示空字符串。


2.2 上下文无关语言(CFG)

如果一个文法的产生式规则形式如下:

(2)  
X → w  
其中 X ∈ V \ Σ(非终结符),w ∈ V*(任意符号序列)

那么该文法称为上下文无关文法(Context-Free Grammar, CFG)

如果一个语言可以由某个 CFG 生成,则它就是上下文无关语言

比如前面提到的语言 L_1 就是上下文无关语言,其 CFG 如下:

G₁ = ({S, a, b}, {a, b}, S, P)

其中 P 包含前面提到的两条规则(1)。


3. 如何证明一个语言是上下文无关语言?

3.1 构造文法(CFG)

最直接的方法是构造一个 CFG 来生成目标语言的所有字符串。例如前面的 L_1 就是通过构造 CFG 来证明的。

但要注意:

  • ✅ 对于结构简单的语言,可以手动设计 CFG。
  • ❌ 对于结构复杂的语言,手动设计 CFG 可能非常困难,甚至不可能。

此时可以考虑使用自动文法学习工具(如基于样本的语法归纳算法)来辅助构造 CFG。

3.2 证明文法的正确性

构造 CFG 后,必须证明两个方向的结论

  1. 该 CFG 生成的语言包含于目标语言
  2. 目标语言的所有字符串都能被该 CFG 生成

否则无法证明 CFG 与目标语言完全等价。

例如对 G₁,我们可以通过归纳法证明其生成的字符串形式为 a^k b^k

3.3 使用下推自动机(PDA)

另一种方法是构建下推自动机(Pushdown Automaton, PDA),它与 CFG 等价。PDA 是一种带有栈结构的有限状态机,可以通过读取输入并操作栈来判断一个字符串是否属于目标语言。

虽然 PDA 的原理较复杂,但在某些情况下比 CFG 更容易构造。


4. 如何证明一个语言不是上下文无关语言?

4.1 Ogden 引理

Ogden 引理是判断语言是否为上下文无关语言的重要工具。它指出:

对于任意上下文无关语言 L,存在一个自然数 n,使得对于任意长度 ≥n 的字符串 w ∈ L,如果其中至少 n 个位置被标记,那么可以将 w 分成五部分:w = xuyvz,满足以下条件:

  • uv 至少包含一个标记位置
  • uyv 最多包含 n 个标记位置
  • 对任意 k ≥ 0,xu^kyv^kz ∈ L

4.2 泵引理(Pumping Lemma)

泵引理是 Ogden 引理的一个特例,适用于所有位置都被标记的情况。其条件如下:

对于任意上下文无关语言 L,存在一个自然数 n,使得任意长度 ≥n 的字符串 w ∈ L 可以被拆分为 w = xuyvz,满足:

  • |uv| ≥ 1
  • |uyv| ≤ n
  • 对任意 k ≥ 0,xu^kyv^kz ∈ L

如果某个字符串不满足这些条件,则说明该语言不是上下文无关语言。

4.3 示例:证明 L_2 = \{a^n b^n c^n \mid n \geq 0\} 不是上下文无关语言

我们假设它是上下文无关语言,然后构造字符串 a^n b^n c^n 并尝试用泵引理进行拆分。

  • 如果 uyv 只包含 a,则泵入后会导致 a 的数量增加,而 b 和 c 数量不变,破坏了结构。
  • 如果 uyv 包含 a 和 b,则泵入后同样破坏了 a、b、c 数量相等的性质。

因此,无法满足泵引理的条件,从而证明 L_2 不是上下文无关语言。


5. 总结

  • ✅ 上下文无关语言可以通过构造 CFG 或 PDA 来证明。
  • ❌ 要证明一个语言不是上下文无关语言,可以使用 Ogden 引理或泵引理。
  • ⚠️ 构造失败并不意味着语言不是上下文无关语言,需谨慎处理。
  • ✅ 对于复杂语言,可以借助自动化工具辅助判断。


原始标题:Context-Free Languages

« 上一篇: B-树数据结构详解
» 下一篇: 红黑树的应用