第 1 章 自动机:方法与体验

自动机、形式化证明、归纳法与形式语言的基础词汇

Source scope
本章以 Hopcroft–Motwani–Ullman《自动机理论、语言和计算导论》第三版中文译本第 1 章为主要依据:中文印刷页 1–24,对应 PDF p.14–37。教材第 2 章从 PDF p.38 开始。本文是自包含学习笔记,不是教材逐字转写;为补足教材略写之处而加入的解释、推导和额外例子,会明确标为“补充说明”或“扩展示例”。

1 0. 本章在整门课中的位置

如果把整门计算理论课程压缩成一句话,它研究的是:

什么可以被计算?什么可以被某种受限模型计算?计算一件事需要多少资源?

后面的 DFA、NFA、正则表达式、CFG、PDA、图灵机、不可判定性和 NP 完全性,都会反复使用第 1 章建立的三套语言:

  1. 模型语言:状态、输入、行为、结构表示;
  2. 证明语言:直接证明、等价证明、逆否、反证、归纳;
  3. 对象语言:字母表、串、语言、问题。

因此第 1 章不是“可以跳过的绪论”。如果本章中的证明方法和符号不熟,后面会在“DFA 等价”“泵引理”“CFG 推导”“不可判定性归约”等位置不断卡住。

1.1 0.1 学习目标

学完本章后,你应该能够:

  • 用“状态 + 输入 + 状态变化”的视角描述一个简单系统;
  • 理解为什么自动机理论既是一门模型理论,也是一门关于可计算性与复杂性的基础理论;
  • 判断一个证明应该使用直接证明、集合双包含、逆否、反证、反例还是归纳;
  • 独立写出标准数学归纳法与结构归纳法的证明骨架;
  • 熟练区分字母表、符号、串、空串、串长、串联接、串的幂、语言;
  • 熟练区分 \(\varnothing\) 与 \(\{\varepsilon\}\);
  • 把一个“是/否问题”理解为某个字母表上的语言。

2 1. 为什么研究自动机理论

2.1 1.1 什么是“自动机”

最朴素地说,自动机(automaton) 是一个按照规则接收输入、维护内部状态并产生行为的抽象机器。

一个状态型系统通常包含三类要素:

  • 状态(state):系统当前“记住”的有限信息;
  • 输入(input):来自外部的事件或符号;
  • 转移(transition):收到输入以后,状态如何改变。

这种观点的重要性在于:很多系统的全部历史非常复杂,但决定下一步行为时并不需要保存整个历史,只需要保存“对未来有用的摘要”。这个摘要就是状态。

2.1.1 例 1:按钮控制的灯

考虑一盏只有 off 和 on 两个状态的灯。每次按下按钮 Push,状态翻转一次。

Two-state automaton toggling between off and on on each Push

两状态按钮自动机:每次 Push 在 off 与 on 之间切换。该图为根据教材思想重新绘制的原创示意图。

这个例子非常小,但已经包含了后面 DFA 的核心思想:

  • 有一个有限状态集合;
  • 有输入事件;
  • 每个“当前状态 + 输入”决定下一状态。

先不要把它和 DFA 的正式五元组混在一起。 第 1 章只是在建立直觉,第 2 章才会给出确定型有穷自动机的正式定义。

2.2 1.2 自动机的一个基本用途:识别模式

自动机可以被看作“识别器”。例如,我们希望在一个字符流中判断是否已经依次看到单词 then。最简单的状态解释是:

  • \(q_0\):还没有匹配任何字符;
  • \(q_1\):已经匹配 t;
  • \(q_2\):已经匹配 th;
  • \(q_3\):已经匹配 the;
  • \(q_4\):已经匹配 then。

States q0 through q4 recognizing t h e n in sequence

单词 then 的线性识别状态示意图。这里只展示“正确匹配路径”;失败字符如何处理将在第 2 章正式设计自动机时处理。

这个例子说明了一个非常重要的建模思想:

状态不是“机器长什么样”,而是“为了完成任务,机器到目前为止必须记住什么”。

后面设计 DFA/NFA 时,真正困难的部分往往不是画箭头,而是找出“应该记住的最小信息”。

2.3 1.3 为什么这种理论值得单独研究

教材开篇强调,自动机理论并不是为了研究几个玩具状态图。它在计算机科学中承担了几类基础角色。

2.3.1 1.3.1 作为软件与硬件系统的抽象模型

状态机适合描述:

  • 数字电路的控制逻辑;
  • 通信协议;
  • 软件界面状态;
  • 词法分析器;
  • 文本模式匹配;
  • 某些控制系统和工作流。

抽象的好处是:我们可以忽略实现细节,只保留与行为正确性有关的部分。

2.3.2 1.3.2 作为“能力边界”的研究工具

对一个计算模型,可以问两个层次的问题:

  1. 它能解决什么问题?
  2. 它不能解决什么问题?

例如,后面会证明:

  • DFA 能识别的恰好是正则语言;
  • PDA 能识别更广的某类语言;
  • 图灵机表达了一般意义上的算法计算;
  • 即使图灵机也存在无法判定的问题。

这就把“程序能不能写出来”从经验问题提升成可以证明的数学命题。

2.3.3 1.3.3 从可判定性到复杂性

仅仅知道“有算法”还不够。还要问:算法是不是足够高效?

因此理论计算机科学里经常区分:

  • 可判定性 / 可计算性(decidability / computability):是否存在算法最终给出正确答案;
  • 易处理性 / 复杂性(tractability / complexity):如果存在算法,它需要多少时间、空间等资源。

本书后半部分会把这条线推进到不可判定性以及 \(P\)、\(NP\)、NP 完全性。

3 2. 结构表示:不要只用自然语言描述系统

自然语言很方便,但容易歧义。形式化方法通常需要一种结构表示(structural representation):把对象的组成方式明确地写出来。

常见结构表示包括:

  • 图(graph):状态作为节点,转移作为边;
  • 表(table):把状态与输入对应到下一状态;
  • 代数式 / 正则表达式:用运算符组合简单模式;
  • 文法(grammar):用产生式递归生成结构;
  • 递归定义:给出基础对象和构造规则;
  • 语法树 / 结构树:显示对象由哪些子对象组合而成。

这些表示不是互相替代的“画法”,而是各自更适合某类证明和算法。后面整门课的一个反复主题就是:

同一个语言可以有多种表示;我们既要证明这些表示等价,也要研究如何在表示之间转换。

4 3. 形式化证明:从“我觉得对”到“我能证明”

自动机理论的大量核心结论都不是靠计算几个例子得到的,而是需要对所有可能输入进行论证。因此必须熟悉证明。

4.1 3.1 命题、定理、引理、推论

  • 命题(proposition):可以判断真假的陈述;
  • 定理(theorem):重要且已经证明的命题;
  • 引理(lemma):通常为证明更大结果服务的中间结论;
  • 推论(corollary):从某个已知结论几乎直接推出的结果。

名称不是重点。重点是:结论必须建立在明确的假设与逻辑推导上。

4.2 3.2 “如果……那么……”的逻辑结构

大量定理可以写成

\[ P \Rightarrow Q. \]

这里:

  • \(P\) 是假设(hypothesis);
  • \(Q\) 是结论(conclusion)。

要证明它,并不是证明 \(P\) 本身,也不是证明 \(Q\) 无条件成立,而是证明:

在假设 \(P\) 成立的前提下,\(Q\) 必然成立。

4.3 3.3 直接证明 / 演绎证明

直接证明的标准形式是:

  1. 假设前提 \(P\);
  2. 使用定义、已知事实和已经证明的定理;
  3. 一步步推出 \(Q\)。

4.3.1 扩展示例:偶数加偶数仍是偶数

要证明:若 \(a,b\) 都是偶数,则 \(a+b\) 是偶数。

根据偶数定义,存在整数 \(m,n\),使得

\[ a=2m,\qquad b=2n. \]

于是

\[ a+b=2m+2n=2(m+n). \]

由于 \(m+n\in\mathbb Z\),所以 \(a+b\) 是偶数。

注意,这个证明的关键不是“举了几个偶数相加的例子”,而是直接展开定义。

5 4. 求助于定义:证明中最常被忽略的第一步

遇到一个术语时,第一反应应该是:

它的正式定义是什么?

例如,要证明一个集合为空、一个整数是偶数、一个串属于某个语言、一个 DFA 接受某个串,首先都应当展开相关定义。

后面很多“看起来很难”的证明,实际上只是:

  1. 写出定义;
  2. 把定义中的量代入;
  3. 做逻辑或代数化简。

5.1 4.1 “当且仅当”必须证明两个方向

命题

\[ P \iff Q \]

等价于同时证明

\[ P\Rightarrow Q \quad\text{和}\quad Q\Rightarrow P. \]

证明时最好明确写出两个方向:

  • 必要性:\(P\Rightarrow Q\);
  • 充分性:\(Q\Rightarrow P\)。

常见错误:证明了一个方向,就写“所以 iff 成立”。这是不完整的。

6 5. 集合相等:最稳妥的方法是双包含

若要证明两个集合 \(R,S\) 相等,最常用的方法是证明:

\[ R\subseteq S \quad\text{且}\quad S\subseteq R. \]

6.1 5.1 标准模板

证明 \(R\subseteq S\):

  1. 任取 \(x\in R\);
  2. 根据 \(R\) 的定义推出关于 \(x\) 的性质;
  3. 推出 \(x\in S\)。

再交换 \(R,S\),证明 \(S\subseteq R\)。

6.2 5.2 为什么这个技巧对形式语言特别重要

语言本质上就是字符串集合。后面我们经常要证明:

  • 两个自动机识别同一个语言;
  • 一个正则表达式与一个 DFA 表示同一个语言;
  • 两个 CFG 生成同一个语言。

于是“语言相等”经常转化成“任意串 \(w\) 属于左边 iff 属于右边”。

7 6. 逆否命题

命题

\[ P\Rightarrow Q \]

与它的逆否命题

\[ \neg Q\Rightarrow \neg P \]

逻辑等价。

因此,当正面从 \(P\) 推到 \(Q\) 很困难,而“假设 \(Q\) 不成立”会提供更强信息时,逆否证明非常有用。

7.0.1 扩展示例:若 \(n^2\) 为偶数,则 \(n\) 为偶数

直接证明并不自然。证明逆否命题:

若 \(n\) 为奇数,则 \(n^2\) 为奇数。

设 \(n=2k+1\),则

\[ n^2=(2k+1)^2=4k^2+4k+1=2(2k^2+2k)+1, \]

所以 \(n^2\) 是奇数。于是原命题成立。

逆命题 \(Q\Rightarrow P\) 与 逆否命题 \(\neg Q\Rightarrow\neg P\) 完全不是一回事。原命题一般不与逆命题等价。

8 7. 反证法

反证法要证明命题 \(P\) 时,先假设 \(\neg P\),再推出矛盾。

证明骨架:

  1. 假设结论不成立;
  2. 连同已有条件继续推理;
  3. 推出不可能事件,例如 \(A\land\neg A\)、违反定义、违反已知定理;
  4. 因而最初的否定假设错误,\(P\) 成立。

反证法在后面的不可判定性证明中非常常见:经常假设“存在一个可以解决某问题的机器”,然后用它构造出逻辑矛盾。

9 8. 反例:推翻全称命题只需要一个例子

要证明

\[ \forall x,\ P(x) \]

是假的,只需要找到一个 \(x_0\),使得 \(P(x_0)\) 不成立。

这就是反例(counterexample)。

例如,命题“所有素数都是奇数”是假的,因为 \(2\) 是素数但不是奇数。

请注意逻辑上的不对称:

  • 证明全称命题:通常必须覆盖所有对象;
  • 推翻全称命题:一个反例就够。

10 9. 数学归纳法

归纳法解决的是这样一类问题:命题 \(P(n)\) 对无穷多个整数 \(n\) 都要成立,我们不可能逐个验证。

10.1 9.1 标准归纳原理

要证明对所有 \(n\ge n_0\),\(P(n)\) 成立,通常分两步:

10.1.1 基础步骤(basis)

证明

\[ P(n_0) \]

成立。

10.1.2 归纳步骤(inductive step)

假设某个 \(k\ge n_0\) 时 \(P(k)\) 成立,这个假设叫归纳假设(inductive hypothesis);然后证明

\[ P(k+1) \]

也成立。

完成这两步后,即可推出 \(P(n)\) 对所有 \(n\ge n_0\) 成立。

10.2 9.2 教材典型例子:平方和公式

教材在归纳部分使用了平方和公式作为典型证明对象:

\[ \sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}. \]

10.2.1 基础步骤

当 \(n=1\) 时,

\[ 1^2=1 = \frac{1\cdot 2\cdot 3}{6}. \]

成立。

10.2.2 归纳假设

假设对 \(n=k\) 成立,即

\[ \sum_{i=1}^{k} i^2 = \frac{k(k+1)(2k+1)}{6}. \]

10.2.3 证明 \(k+1\)

\[ \begin{aligned} \sum_{i=1}^{k+1} i^2 &= \left(\sum_{i=1}^{k} i^2\right)+(k+1)^2\\ &= \frac{k(k+1)(2k+1)}{6}+(k+1)^2\\ &= (k+1)\left(\frac{k(2k+1)}{6}+k+1\right)\\ &= (k+1)\frac{2k^2+7k+6}{6}\\ &= \frac{(k+1)(k+2)(2k+3)}{6}. \end{aligned} \]

而这正是把 \(n\) 替换为 \(k+1\) 后的右端:

\[ \frac{(k+1)((k+1)+1)(2(k+1)+1)}{6}. \]

所以归纳步骤成立。

10.3 9.3 教材中的另一个典型增长比较

教材还通过类似

\[ 2^n>n^2\qquad(n>4) \]

的命题展示归纳推理。

10.3.1 基础情况

\[ 2^5=32>25=5^2. \]

10.3.2 归纳假设

假设 \(2^k>k^2\),其中 \(k\ge5\)。

则

\[ 2^{k+1}=2\cdot 2^k>2k^2. \]

只需再验证

\[ 2k^2>(k+1)^2. \]

等价于

\[ k^2-2k-1>0. \]

对 \(k\ge5\) 显然成立。因此 \(2^{k+1}>(k+1)^2\)。

这个例子提醒我们:

归纳步骤中不能只说“显然继续成立”,必须真正把 \(P(k)\) 转化为 \(P(k+1)\)。

11 10. 更一般的整数归纳

教材随后把标准归纳推广到更一般的形式。学习时至少要掌握以下三种变体。

11.1 10.1 从任意起点 \(n_0\) 开始

并不是所有命题都从 \(n=0\) 或 \(n=1\) 开始。例如上面的 \(2^n>n^2\) 从 \(n=5\) 才适合作为严格不等式的起点。

11.2 10.2 多个基础情况

如果 \(P(k+1)\) 的证明需要用到多个之前的值,例如 \(P(k)\) 与 \(P(k-1)\),那么往往要先验证多个基础情况。

11.3 10.3 强归纳(补充说明)

强归纳的归纳假设是:

\[ P(n_0),P(n_0+1),\dots,P(k) \]

全部成立,然后证明 \(P(k+1)\)。

它与普通归纳在逻辑能力上等价,但在“一个对象由多个更小对象组成”的证明里更自然。

12 11. 结构归纳法

整数归纳是沿着

\[ 0,1,2,3,\dots \]

这样的线性结构递推;而很多计算机科学对象不是按整数线性生成,而是递归构造出来的,例如:

  • 算术表达式;
  • 语法树;
  • 正则表达式;
  • CFG 推导树;
  • 递归定义的字符串集合。

这时使用结构归纳(structural induction)。

12.1 11.1 结构归纳的两部分

假设集合 \(S\) 通过以下方式递归定义:

  1. 一些基础对象属于 \(S\);
  2. 如果若干较小对象属于 \(S\),那么通过某些构造规则可得到新对象,且新对象也属于 \(S\)。

要证明 \(S\) 中每个对象都具有性质 \(P\),就证明:

  • 基础情况:每个基础对象都有性质 \(P\);
  • 归纳构造:假设参与构造的子对象都有性质 \(P\),证明构造出的新对象也有性质 \(P\)。

A recursive tree with basis leaves and inductive construction at internal nodes

结构归纳与递归构造的对应关系:先证明叶子,再证明构造节点能保持性质。

12.2 11.2 为什么它会贯穿本书

后面很多对象本身就是递归定义的:

  • 正则表达式由基本表达式通过并、连接、闭包构成;
  • CFG 推导树由产生式递归构成;
  • 某些机器描述和公式也可递归定义。

所以证明“所有合法表达式都具有某性质”时,最自然的证明结构往往就是结构归纳。

13 12. 互归纳法

有时两个性质彼此依赖:证明 \(P\) 需要 \(Q\),证明 \(Q\) 又需要 \(P\)。这时可以把它们捆绑成一个更强的归纳命题一起证明,称为互归纳(mutual induction)。

典型骨架:

  1. 同时给出 \(P\) 和 \(Q\) 的基础情况;
  2. 假设较小结构上 \(P,Q\) 都成立;
  3. 分别证明新结构上的 \(P,Q\) 都成立。

这不是“循环论证”,因为归纳假设只用于更小的对象。

14 13. 自动机理论的中心概念:字母表、串与语言

从这里开始,进入后面整本书都不会离开的核心词汇。

15 14. 字母表 \(\Sigma\)

字母表(alphabet) 是一个有限的、非空的符号集合,通常记为

\[ \Sigma. \]

例如:

\[ \Sigma=\{0,1\} \]

是二进制字母表;

\[ \Sigma=\{a,b,c\} \]

也是一个字母表。

注意:

  • 字母表中的元素叫符号(symbol);
  • “符号”可以是字符,也可以是我们抽象出来的 token;
  • 字母表是一个集合,所以不关心元素的排列顺序。

16 15. 串(string)

在字母表 \(\Sigma\) 上的一个串,是由 \(\Sigma\) 中符号组成的有限序列。

若

\[ \Sigma=\{0,1\}, \]

那么

\[ 0,\quad 101,\quad 001011 \]

都是 \(\Sigma\) 上的串。

16.1 15.1 空串 \(\varepsilon\)

长度为 0 的唯一字符串叫空串(empty string),记为

\[ \varepsilon. \]

它不包含任何符号。

特别注意:

\[ \varepsilon \neq \varnothing. \]

因为:

  • \(\varepsilon\) 是一个字符串;
  • \(\varnothing\) 是一个集合,而且没有任何元素。

更进一步:

\[ \{\varepsilon\}\neq\varnothing. \]

因为 \(\{\varepsilon\}\) 是一个含有一个元素的集合,这个唯一元素恰好是空串。

这是自动机理论最经典的符号陷阱之一。

16.2 15.2 串的长度

串 \(w\) 的长度记为

\[ |w|. \]

例如:

\[ |10110|=5, \qquad |\varepsilon|=0. \]

16.3 15.3 串的联接(concatenation)

若 \(x,y\) 是两个串,\(xy\) 表示先写 \(x\),再紧跟 \(y\)。

例如:

\[ x=01,\qquad y=110, \]

则

\[ xy=01110. \]

联接满足:

16.3.1 结合律

\[ (xy)z=x(yz). \]

因此通常可以直接写 \(xyz\)。

16.3.2 空串是单位元

\[ \varepsilon w=w\varepsilon=w. \]

16.3.3 一般不满足交换律

通常

\[ xy\neq yx. \]

例如 \(x=0,y=1\),则 \(xy=01\),而 \(yx=10\)。

16.3.4 长度可加

\[ |xy|=|x|+|y|. \]

16.4 15.4 串的幂

定义:

\[ w^0=\varepsilon, \]

并且对 \(k\ge1\),

\[ w^k=\underbrace{ww\cdots w}_{k\text{ 次}}. \]

例如若 \(w=ab\),则

\[ w^3=ababab. \]

17 16. \(\Sigma^k\)、\(\Sigma^*\) 与 \(\Sigma^+\)

这些记号会在后面频繁出现。

17.1 16.1 固定长度字符串集合 \(\Sigma^k\)

\[ \Sigma^k \]

表示 \(\Sigma\) 上所有长度恰好为 \(k\) 的字符串集合。

特别地:

\[ \Sigma^0=\{\varepsilon\}. \]

17.2 16.2 Kleene 星号 \(\Sigma^*\)

\[ \Sigma^*=\bigcup_{k\ge0}\Sigma^k. \]

即 \(\Sigma\) 上所有有限字符串组成的集合,其中包括空串。

17.3 16.3 正闭包 \(\Sigma^+\)

\[ \Sigma^+=\bigcup_{k\ge1}\Sigma^k. \]

所以

\[ \Sigma^+=\Sigma^*\setminus\{\varepsilon\}. \]

前提是 \(\Sigma\) 是非空字母表。

18 17. 语言(language)

给定字母表 \(\Sigma\),语言就是 \(\Sigma^*\) 的任意子集:

\[ L\subseteq\Sigma^*. \]

这个定义非常宽:

  • 语言可以是有限集;
  • 也可以是无限集;
  • 可以包含 \(\varepsilon\);
  • 也可以不包含;
  • \(\varnothing\) 本身也是语言;
  • \(\{\varepsilon\}\) 也是语言。

18.1 17.1 例子

在 \(\Sigma=\{0,1\}\) 上:

18.1.1 语言 A:所有以 1 结尾的串

\[ L_A=\{w\in\{0,1\}^*: w\text{ 以 }1\text{ 结尾}\}. \]

18.1.2 语言 B:0 和 1 数量相同的串

\[ L_B=\{w\in\{0,1\}^*: \#_0(w)=\#_1(w)\}. \]

其中 \(\#_0(w)\) 表示 \(w\) 中 0 的出现次数。

18.1.3 语言 C:先若干个 0,再同样多的 1

\[ L_C=\{0^n1^n:n\ge0\}. \]

这里 \(\varepsilon\in L_C\),因为取 \(n=0\) 时

\[ 0^01^0=\varepsilon\varepsilon=\varepsilon. \]

这个语言之后会成为区分“正则语言”和“上下文无关语言”的经典例子。

18.2 17.2 用集合构造式定义语言

形式语言经常写成

\[ \{w\in\Sigma^*: P(w)\}. \]

它表示:所有满足性质 \(P\) 的字符串 \(w\)。

学习自动机设计时,一个非常实用的顺序是:

  1. 先用一句自然语言描述目标集合;
  2. 再用集合构造式把语言写清楚;
  3. 最后设计自动机或其他表示。

这样可以避免“图画出来了,但自己都说不清它究竟识别什么语言”。

19 18. “问题”为什么可以看成语言

自动机理论与复杂性理论通常研究判定问题(decision problem),也就是答案只有“是/否”的问题。

把一个判定问题变成语言,需要两步:

  1. 规定如何把每个问题实例编码成字符串;
  2. 把所有答案为“是”的实例编码收集成一个语言。

于是:

\[ L_{\text{problem}} = \{\operatorname{enc}(x): x\text{ 是 YES 实例}\}. \]

一个算法“解决这个问题”,就等价于它能够对任意合法编码 \(w\) 判断

\[ w\in L_{\text{problem}}? \]

这一步极其重要,因为它把现实中的计算问题统一转成“语言成员性”问题。

19.1 18.1 为什么这会贯穿后半本书

以后讨论:

  • 某问题是否可判定;
  • 某语言是否属于 \(P\);
  • 某问题是否 NP 完全;
  • 一个问题如何归约到另一个问题;

本质上都依赖“问题 \(\leftrightarrow\) 语言”的对应。

20 19. 本章最容易混淆的概念

容易混淆 正确区分
\(\varnothing\) 与 \(\varepsilon\) 前者是空集合,后者是长度 0 的串
\(\varnothing\) 与 \(\{\varepsilon\}\) 前者有 0 个元素,后者有 1 个元素
符号 0 与串 0 语境中写法相同,但概念层级不同:前者是字母表元素,后者是长度 1 的串
\(\Sigma\) 与 \(\Sigma^*\) 前者是符号集合,后者是所有有限串的集合
直接证明与举例验证 举例只能提供直觉,不能证明全称命题
逆命题与逆否命题 原命题与逆否命题等价,与逆命题一般不等价
归纳假设与待证结论 只能假设 \(P(k)\),不能偷假设 \(P(k+1)\)
“自动机画法”与“状态含义” 先定义状态需要记住的信息,再画图

21 20. 一张表记住第 1 章

主题 核心问题 关键形式
自动机 系统为了未来行为要记住什么? 状态 + 输入 + 转移
可判定性 是否存在总能终止并给出答案的算法? YES/NO 问题
复杂性 算法需要多少资源? 时间、空间等
直接证明 如何从假设推出结论? \(P\Rightarrow Q\)
集合相等 如何证明两个集合完全一致? 双包含
逆否 正面难推时怎么办? \(\neg Q\Rightarrow\neg P\)
反证 否定结论会怎样? 推出矛盾
反例 如何推翻全称命题? 找一个失败对象
整数归纳 如何证明无穷多个整数情况? 基础 + \(k\to k+1\)
结构归纳 如何证明所有递归结构? 基础构件 + 构造规则
字母表 可以使用哪些原子符号? \(\Sigma\)
串 符号组成的有限序列 \(w\in\Sigma^*\)
空串 长度为 0 的串 \(\varepsilon\)
语言 哪些串属于目标集合? \(L\subseteq\Sigma^*\)
判定问题 哪些实例答案为 YES? YES 编码组成语言

22 21. 与后续章节的连接

本章的概念会按下面的路线继续生长:

状态直觉
  ↓
DFA / NFA / ε-NFA(第2章)
  ↓
正则表达式与表示等价(第3章)
  ↓
泵引理、封闭性、最小化(第4章)

字符串 / 语言
  ↓
CFG(第5章)
  ↓
PDA(第6章)
  ↓
CFL 的性质(第7章)

问题 = 语言
  ↓
图灵机(第8章)
  ↓
不可判定性与归约(第9章)
  ↓
P / NP / NP 完全性(第10章)

证明方法同样贯穿全书:

  • 双包含:证明语言等价;
  • 归纳:证明扩展转移函数、递归结构性质;
  • 结构归纳:证明正则表达式、文法结构上的命题;
  • 反证:不可判定性;
  • 反例:推翻封闭性猜想或错误等价命题。

23 22. 学习完成标准

如果不看教材,你应该能独立回答下面这些问题:

  1. 为什么“状态”可以理解为对历史的压缩?
  2. 自动机理论中的“可判定性”和“复杂性”有什么区别?
  3. 为什么证明 \(A=B\) 通常要证明两个包含关系?
  4. 原命题、逆命题、逆否命题之间是什么关系?
  5. 数学归纳法为什么不是“验证很多例子”?
  6. 结构归纳和普通整数归纳的对象有什么不同?
  7. \(\varnothing\)、\(\varepsilon\)、\(\{\varepsilon\}\) 分别是什么?
  8. \(\Sigma^*\) 为什么一定包含 \(\varepsilon\)?
  9. 语言为什么本质上只是字符串集合?
  10. 为什么一个判定问题可以编码成一个语言?

能清楚回答这 10 个问题,就具备进入第 2 章 DFA/NFA 的基础。