形式语言与自动机总结笔记

2023-11-03

形式语言与自动机

教学大纲

  • 正则语言
    • 2 有穷自动机
      2.1 确定的有穷自动机
      2.2 非确定有穷自动机
      2.3 带有空转移的非确定有穷自动机
    • 3 正则表达式
      3.1 正则表达式
      3.2 自动机和正则表达式
      3.3 正则表达式的代数定律
    • 4 正则语言的性质
      4.1 正则语言的泵引理
      4.2 正则语言的封闭性
      4.3 正则语言的判定性质
      4.4 自动机最小化
  • 上下文无关语言
    • 5 上下文无关文法
      5.1 上下文无关文法
      5.2 语法分析树
      5.3 文法和语言的歧义性
      5.4 文法的化简和范式
    • 6 下推自动机
      6.1 下推自动机
      6.2 下推自动机的语言
      6.3 下推自动机与文法的等价性
      6.4 确定性下推自动机
    • 7 上下文无关语言的性质
      7.1 上下文无关语言的泵引理
      7.2 上下文无关语言的封闭性
      7.3 上下文无关语言的判定性质
  • 计算导论
    • 8.1 图灵机及其扩展
    • 8.2 不可判定性

主要考点

  • 构造自动机:DFA、NFA、ε-NFA、PDA、DPDA、TM
  • 设计正则表达式/正则文法、上下文无关文法
  • 泵引理+封闭性证明不是正则语言
  • 等价性转换
    • NFA和DFA
    • FA和正则表达式
    • PDA和CFG
  • CNF和GNF
  • 语言的接受和设计

文章目录

1. 确定的有穷自动机(DFA)

确定的有穷自动机(DFA, Deterministic Finite Automaton) A 为五元组
A = ( Q , Σ , δ , q 0 , F ) A = (Q, Σ, δ, q0, F) A=(Q,Σ,δ,q0,F)

  1. Q Q Q : 有穷状态集;
  2. Σ Σ Σ : 有穷输入符号集或字母表;
  3. δ δ δ : Q × Σ → Q Q × Σ → Q Q×ΣQ, 状态转移函数;
  4. q 0 q^0 q0 ∈ Q : 初始状态;
  5. F ⊆ Q F ⊆ Q FQ : 终结状态集或接受状态集.

例:请设计 DFA, 在任何由 0 和 1 构成的串中, 接受含有 01 子串的全部串.

  1. 未发现 01, 即使 0 都还没出现过;
  2. 未发现 01, 但刚刚读入字符是 0;
  3. 已经发现了 01

因此 DFA A 的可定义为:
A   =   ( { q 1 ,   q 2 ,   q 3 } ,   { 0 ,   1 } ,   δ ,   q 1 ,   { q 3 } ) A\ = \ (\{ q1,\ q2,\ q3\},\ \{ 0,\ 1\},\ \delta,\ q1,\ \{ q3\}) A = ({q1, q2, q3}, {0, 1}, δ, q1, {q3})

  • 其中 δ 为:
    δ ( q 1 , 1 ) = q 1 δ(q1, 1) = q1 δ(q1,1)=q1
    δ ( q 2 , 1 ) = q 3 δ(q2, 1) = q3 δ(q2,1)=q3
    δ ( q 3 , 1 ) = q 3 δ(q3, 1) = q3 δ(q3,1)=q3
    δ ( q 1 , 0 ) = q 2 δ(q1, 0) = q2 δ(q1,0)=q2
    δ ( q 2 , 0 ) = q 2 δ(q2, 0) = q2 δ(q2,0)=q2
    δ ( q 3 , 0 ) = q 3 δ(q3, 0) = q3 δ(q3,0)=q3

  • 状态转移图

    • 每个状态 q 对应一个节点, 用圆圈表示;
    • 状态转移 δ(q, a) = p 为一条从 q 到 p 且标记为字符 a 的有向边;
    • 开始状态 q0 用一个标有 start 的箭头表示;
    • 接受状态的节点, 用双圆圈表示.
  • 状态转移表

2. 非确定的有穷自动机(NFA)

非确定有穷自动机(NFA, Nondeterministic Finite Automaton) A 为五元组
A = ( Q , Σ , δ , q 0 , F ) A = (Q, Σ, δ, q0, F) A=(Q,Σ,δ,q0,F)

  1. Q Q Q : 有穷状态集;
  2. Σ Σ Σ : 有穷输入符号集或字母表;
  3. δ δ δ : Q × Σ = 2 Q Q \times \Sigma = 2^{Q} Q×Σ=2Q, 状态转移函数;
  4. q 0 q^0 q0 ∈ Q : 初始状态;
  5. F ⊆ Q F ⊆ Q FQ : 终结状态集或接受状态集.

与DFA区别

  • δ δ δ : Q × Σ = 2 Q Q \times \Sigma = 2^{Q} Q×Σ=2Q
  • 转移后为一个状态集合
  • 同一个状态在相同的输入下,可以有多个转移状态
  • 自动机可以处在多个当前状态

例:接受全部以 01 结尾的串的 NFA.

解:五元组为 A   =   ( { q 0 ,   q 1 ,   q 2 } ,   { 0 ,   1 } ,   δ ,   q 0 ,   { q 2 } ) A\ = \ (\{ q0,\ q1,\ q2\},\ \{ 0,\ 1\},\ \delta,\ q0,\ \{ q2\}) A = ({q0, q1, q2}, {0, 1}, δ, q0, {q2})
转移函数 δ:

  • δ ( q 0 ,   0 )   =   { q 0 ,   q 1 } \delta(q0,\ 0)\ = \ \{ q0,\ q1\} δ(q0, 0) = {q0, q1}
  • δ ( q 1 ,   0 )   =   ∅ \delta(q1,\ 0)\ = \ \varnothing δ(q1, 0) = 
  • δ ( q 2 ,   0 )   =   ∅ \delta(q2,\ 0)\ = \ \varnothing δ(q2, 0) = 
  • δ ( q 0 ,   1 )   =   { q 0 } \delta(q0,\ 1)\ = \ \{ q0\} δ(q0, 1) = {q0}
  • δ ( q 1 ,   1 )   =   { q 2 } \delta(q1,\ 1)\ = \ \{ q2\} δ(q1, 1) = {q2}
  • δ ( q 2 ,   1 )   =   ∅ \delta(q2,\ 1)\ = \ \varnothing δ(q2, 1) = 

3. 带有空转移的非确定有穷自动机(ε-NFA)

DFA、NFA和ε-NFA性质:

  • 自动机在某状态, 读入某个字符时, 可能有多个转移
  • 自动机在某状态, 读入某个字符时, 可能没有转移
  • 自动机在某状态, 可能不读入字符, 就进行转移

ε-NFA与NFA

  • 不读入字符,就进行转移的NFA
  • Q × ( Σ ∪ { ε } ) = 2 Q Q \times (\Sigma \cup \left\{ \varepsilon \right\}) = 2^{Q} Q×(Σ{ε})=2Q

例:语言 L = w ∈ 0 , 1 ∗ ∣ w 倒 数 3 个 字 符 至 少 有 一 个 是 1 L = {w ∈ {0, 1}∗ | w 倒数 3 个字符至少有一个是 1} L=w0,1w31 的ε-NFA.

  • 状态转移图
  • 状态转移表

此后, 不再明确区分 ε-NFA 和 NFA, 而认为它们都是 NFA.

4. DFA和NFA的等价性与转换

ε − 闭 包 : q 0 → 所 有 q 0 能 到 达 的 状 态 的 集 合 ε-闭包: {q_0} → {所有q_0能到达的状态的集合} εq0q0
记为 E c l o s e ( q ) Eclose(q) Eclose(q)

例:求以下状态的 ε − c l o s u r e ε - closure εclosure

解:

  • E ( 1 ) = { 1 , 2 , 4 , 3 , 6 } E(1) = \{ 1, 2, 4, 3, 6 \} E(1)={1,2,4,3,6}
  • E ( 2 ) = { 2 , 3 , 6 } E(2) = \{ 2, 3, 6 \} E(2)={2,3,6}
  • E ( 3 ) = { 3 , 6 } E(3) = \{ 3, 6 \} E(3)={3,6}
  • E ( 4 ) = { 4 } E(4) = \{ 4 \} E(4)={4}
  • E ( 5 ) = { 5 , 7 } E(5) = \{ 5, 7 \} E(5)={5,7}
  • E ( 6 ) = { 6 } E(6) = \{ 6 \} E(6)={6}
  • E ( 7 ) = { 7 } E(7) = \{ 7 \} E(7)={7}

扩展转移函数

例:将以下NFA转换为DFA

解:

  • 状态转移表和ε-闭包为
  • 设置初状态 { q 0 } \{q_0 \} {q0}
    • 当输入0时, { q 0 } → { q 0 } \{q_0\} → \{q_0\} {q0}{q0},不变,则 { q 0 } \{q_0\} {q0}的ε-闭包还是为 { q 0 } \{q_0\} {q0}
    • 当输入1时, { q 0 } → { q 0 , q 1 } \{q_0\} → \{q_0, q_1\} {q0}{q0,q1},则 { q 0 , q 1 } \{q_0, q_1\} {q0,q1}的ε-闭包为 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3}
  • 因此状态转移函数如下
0 0 0 1 1 1
{ q 0 } \{q_0\} {q0} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3}
  • 出现新状态 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
    • 当输入0时, { q 0 , q 1 , q 2 , q 3 } → { q 0 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} → \{q_0, q_2, q_3\} {q0,q1,q2,q3}{q0,q2,q3},则 { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3}的ε-闭包为 { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3}
    • 当输入1时, { q 0 , q 1 , q 2 , q 3 } → { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} → \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3}{q0,q1,q2,q3},则 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3}的ε-闭包为 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3}
  • 因此状态转移函数如下
0 0 0 1 1 1
{ q 0 } \{q_0\} {q0} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3} { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
  • 出现新状态 { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3}
    • 当输入0时, { q 0 , q 2 , q 3 } → { q 0 , q 3 } \{q_0, q_2, q_3\} → \{q_0, q_3\} {q0,q2,q3}{q0,q3},则 { q 0 , q 3 } \{q_0, q_3\} {q0,q3}的ε-闭包为 { q 0 , q 3 } \{q_0, q_3\} {q0,q3}(红色为原转移,绿色为转移后的闭包)
    • 当输入1时, { q 0 , q 2 , q 3 } → { q 0 , q 1 , q 2 , q 3 } \{q_0, q_2, q_3\} → \{q_0, q_1, q_2, q_3\} {q0,q2,q3}{q0,q1,q2,q3},则 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}的ε-闭包为 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
  • 因此状态转移函数如下
0 0 0 1 1 1
{ q 0 } \{q_0\} {q0} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3} { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 3 } \{q_0, q_3\} {q0,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
  • 出现新状态 { q 0 , q 3 } \{q_0, q_3\} {q0,q3}
  • 同理,因此状态转移函数如下
0 0 0 1 1 1
{ q 0 } \{q_0\} {q0} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3} { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 3 } \{q_0, q_3\} {q0,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
{ q 0 , q 3 } \{q_0, q_3\} {q0,q3} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
  • 最后,将 q 0 q_0 q0设为初始状态,且将含有原转移终止符( q 3 q_3 q3)的状态设置为终止状态,即 { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3} { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 3 } \{q_0, q_3\} {q0,q3}均为终止状态
0 0 0 1 1 1
→ { q 0 } →\{q_0\} {q0} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
∗ { q 0 , q 1 , q 2 , q 3 } * \{q_0, q_1,q_2, q_3\} {q0,q1,q2,q3} { q 0 , q 2 , q 3 } \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
∗ { q 0 , q 2 , q 3 } * \{q_0, q_2, q_3\} {q0,q2,q3} { q 0 , q 3 } \{q_0, q_3\} {q0,q3} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}
∗ { q 0 , q 3 } * \{q_0, q_3\} {q0,q3} { q 0 } \{q_0\} {q0} { q 0 , q 1 , q 2 , q 3 } \{q_0, q_1, q_2, q_3\} {q0,q1,q2,q3}

5. DFA化简:状态等价性和填表算法

5.1 等价和可区分

对于任意两个状态,一定是

  • 等价
  • 可区分

二者之一

  • 等价

    • 即:当两个状态为等价时,对于任意一个输入符,转移状态同时为终止状态或同时不是
      • 注:不一定相同
      • 因此:不提及两个状态的转移状态是否相同
  • 可区分

    • 即:当两个状态为可区分时(不等价),存在至少一个输入符,转移状态不同时为终止(不同时为非终止)

例:化简以下DFA

5.2 填表算法 Table-Filling Algorithm

  1. 直接标记终态和非终态之间的状态对
  2. 标记所有经过字符 0 到达终态和非终态的状态对
    - {D, F }×{A, B, C, E, G, H}
  3. 标记所有经过字符 1 到达终态和非终态的状态对
    - {B, H }×{A, C, D, E, F, G}
  4. 此时还有 [A,E], [A,G], [B,H], [D,F], [E,G] 未标记, 只需逐个检查.
    - [A,G] 是可区分的, 因为经串 01 到可区分的 [C,E];
    - [E,G] 是可区分的, 因为经串 10 到可区分的 [C,H].
  5. [A,E], [B,H] 和 [D,F] 在经过很短的字符串后, 都会到达相同状态,因此都是等价的.
  • 填表完成后如下图
  • 合并等价状态(最小化)

6. 正则表达式(Regular Express)

语言是字符串集合。
语言的运算:并、连接、幂、克林闭包

递归定义:
如果E为字母表,则2上的正则表达式递归定义为:

  • 0是一个正则表达式,表示空语言;
  • ε ε ε是一个正则表达式,表示语言{e};
  • 任意 a ∈ E a∈E aE,a是一个正则表达式,表示语言{a};
  • 如果正则表达式 r 和 s 分别表示语言 R R R S S S,那么 r + s , r s , r ∗ 和 ( r ) r+s,rs, r^*和 ( r ) r+srs,r(r)都是正则表达式
  • 分别表示语言 R ∪ S , R ⋅ S , R ∗ 和 R R∪S,R·S,R*和R RSRSRR

优先级:括号>星(*)>连接(×)>加(+)

例:L = {w | w ∈ {0, 1}∗ and w has no pair of consecutive 0’s.}

  • 解:1∗(011∗)∗(0 + ε) 或 (1 + 01)∗(0 + ε)

7. 正则表达式和有穷自动机的等价关系与转换

  • 正则表达式与有穷自动机等价
  • 有穷自动机可以识别正则语言
  • 正则表达式生成正则语言

7.1 正则表达式–>自动机

正则表达式到自动机的转换分为以下4种

  • 连接(乘法)
  • 并(加法)
  • 幂(星)
  • 闭包

例:正则表达式 ( 0 + 1 ) ∗ 1 ( 0 + 1 ) (0+1)^*1(0+1) (0+1)1(0+1)转换为 ε − N F A ε-NFA εNFA

7.1.1 并(加号)的转换

例: 0 + 1 0+1 0+1

7.1.2 幂(星号)的转换

例: ( 0 + 1 ) ∗ (0+1)^* (0+1)

  • 蓝色圈内为一个整体,表示幂运算的底
  • 上方的红箭头是递归,即循环出现
  • 下方的红箭头是蓝色圈内内容一个都不出现的情况,对应该题 ε ε ε,即空串情况

7.2 自动机–>正则表达式

若干例题

  • 通过7.1的逆向推导得出


2.

3.

7.2.1 删除状态法

  1. 添加首尾两个状态;
  2. 从最小的单元开始化简为正则表达式,去掉这个单元,新增一条边,写上转换的表达式;
  3. 最后一条表达式即为结果;

7.2.2 归纳法

  • Pick every label on the path from q 0 q_0 q0 to q 2 q_2 q2 ---- one by one
  • Form every R e g E x p RegExp RegExp on the path from q 0 q_0 q0 to q 2 q_2 q2 ---- one by one

R i j ( k ) : 0 < = k < = n R_{ij}^{(k)}: 0<=k<=n Rij(k):0<=k<=n i i i j j j路径上的正则表达式

  • no inner node is greater than k


当k≥1时进行归纳法
公式

例:

解:
在这里插入图片描述

8. 正则语言的性质

8.1 泵引理

  • 确定一个语言是正则语言?
      • DFA
      • NFA
      • ε-NFA
      • 正则表达式
      • 泵引理,反证法

即:前 N N N的字符中存在一段可以在该位置循环出现
泵引理只是正则语言的必要条件,只能用来证明某个语言不是正则的

证明



8.2 封闭性

正则语言经某些运算后得到的新语言仍保持正则,称正则语言在这些运算下封闭

正则语言 L 和 M, 在这些运算下封闭

  • 并: L ∪ M L \cup M LM
  • 连接: L M LM LM
  • 闭包: L ∗ L^* L
  • 补: L ‾ \overline{L} L
  • 差: L − M L-M LM
  • 交: L ∩ M L \cap M LM
  • 反转: L R = { w R ∣ w ϵ L } L^{R} = \left\{ w^{R}|w\epsilon L \right\} LR={wRwϵL}
  • 同态
  • 逆同态

考点:能够运用这些性质,结合泵引理证明一个语言是否是正则语言

自动机的转换

  • 并:使用 ε − N F A ε-NFA εNFA,新建初始状态节点,空转移到原来的初始状态;
  • 连接:前者终止状态空转移到后者初始状态;
  • 闭包:增加新终止状态,原终止状态空转移到新终止状态以及初始状态;
  • 补:终止状态取补
  • 反转:新增终止状态,原终止状态空转移到新终止状态,然后所有边逆向,是(非)终止状态改为非(是)终止状态;

证明思路

9. 上下文无关文法(CFG)

定义:上下文无关文法(CFG, 简称文法) G 是一个四元组 G = ( V , T , P , S ) G = (V, T, P, S) G=(V,T,P,S)

  • V V V : 变元的有穷集, 变元也称为非终结符或语法范畴;
  • T T T: 终结符的有穷集, 且 V ∩ T = ∅;
  • P P P: 产生式的有穷集, 每个产生式包括:
    • 一个变元, 称为“产生式的头或左部”;
    • 一个产生式符号 →, 读作“定义为”;
    • 一个 ( V ∪ T ) ∗ (V ∪ T)^* (VT)中的符号串, 称为“体或右部”;
  • S ∈ V S ∈V SV:初始符号, 文法开始的地方.

产生

  • 产生式 A → α A → α Aα,读作 A 定义为 α
  • 如果有多个 A 的产生式 A → α 1 , A → α 2 , ⋅ ⋅ ⋅ , A → α n A → α_1, A → α_2, · · · , A → α_n Aα1,Aα2,,Aαn
  • 可简写为 A → α 1 ∣ α 2 ∣ ⋅ ⋅ ⋅ ∣ α n A → α_1 | α_2 | · · · | α_n Aα1α2αn
  • 文法中变元 A 的全体产生式, 称为 A 产生式

符号

  • 终结符: 0, 1, . . . , a, b, . . .
  • 终结符串: . . . , w, x, y, z
  • 非终结符: S, A, B, . . .
  • 终结符或非终结符: . . . , X, Y, Z
  • 终结符或非终结符组成的串: α, β, γ, . . .

例:

  • 回文
    G = ( A , 0 , 1 , A → ε ∣ 0 ∣ 1 ∣ 0 A 0 ∣ 1 A 1 , A ) G = ({A}, {0, 1}, {A → ε | 0 | 1 | 0A0 | 1A1}, A) G=(A,0,1,Aε010A01A1,A)
  • L={ w∈{0,1}* | w contains same number of 0’s and 1’s }
    R = ( S , 0 , 1 , P , S ) R = ({S }, {0,1}, P, S ) R=(S,0,1,P,S)
    P : S → ε ∣ 0 S 1 ∣ 1 S 0 ∣ S S P:S → ε | 0S1 | 1S0 | SS PSε0S11S0SS
  • 从字符串到文法变元的分析过程, 称为递归推理或归约;
    归约: 自底向上, 由产生式的体向头的分析
  • 从文法变元到字符串的分析过程, 称为推导或派生.
    派生: 自顶向下, 由产生式的头向体分析

9.1 规约

例:用算数表达式文法 G e x p G_{exp} Gexp, 将 a ∗ ( a + b 00 ) a ∗ (a + b00) a(a+b00) 归约的过程

  1. E → I
  2. E → E + E
  3. E → E ∗ E
  4. E → (E)
  5. I → a
  6. I → b
  7. I → Ia
  8. I → Ib
  9. I → I0
  10. I → I1

目标:从 a ∗ ( a + b 00 ) a ∗ (a + b00) a(a+b00)规约到 E E E

解:

  • a ∗ ( a + b 00 ) a ∗ (a + b00) a(a+b00)
  • I ∗ ( I + b 00 ) I ∗ (I + b00) I(I+b00)
  • I ∗ ( I + I 00 ) I ∗ (I + I00) I(I+I00)
  • I ∗ ( I + I 0 ) I ∗ (I + I0) I(I+I0)
  • I ∗ ( I + I ) I ∗ (I + I) I(I+I)
  • E ∗ ( E + E ) E ∗ (E + E) E(E+E)
  • E ∗ E E ∗ E EE
  • E E E

即:

9.2 派生

  • 最左派生
  • 最右派生

为限制派生的随意性, 要求只替换符号串中最左边变元的派生过程, 称为
左派生
, 记为
⟹ l m 或 ⟹ lm ∗ \underset{lm}{\Longrightarrow} 或 \overset{*}{\underset{\text{lm}}{\Longrightarrow}} lmlm
只替换最右的, 称为最右派生, 记为
⟹ r m 或 ⟹ rm ∗ \underset{rm}{\Longrightarrow} 或 \overset{*}{\underset{\text{rm}}{\Longrightarrow}} rmrm
任何派生都有等价的最左派生和最右派生

  • A ⟹ ∗ w A\overset{*}{\Longrightarrow}w Aw 当且仅当 A ⟹ lm ∗ w A\overset{*}{\underset{\text{lm}}{\Longrightarrow}}w Almw 当且仅当 A ⟹ rm ∗ w A\overset{*}{\underset{\text{rm}}{\Longrightarrow}}w Armw
  • 即:最左和最右派生同时存在或不存在

w w w L ( G ) L(G) L(G)中时满足:

  • w w w仅由终结符组成
  • 初始符号 S S S能派生出 w w w

即:
L ( G ) = { w   ∣   w ϵ T ∗ ,   S ⟹ G ∗ w } L\left( G \right) = \left\{ w\ |\ w\epsilon T^{*},\ S\overset{*}{\underset{G}{\Longrightarrow}}w \right\} L(G)={w  wϵT, SGw}

语言 L 是某个 CFG G 定义的语言, 即 L = L ( G ) L = L(G) L=L(G), 则称 L 为上下文无关语言(CFL, Context-Free Language).

  • 上下文无关是指在文法派生的每一步 α A β ⇒ α γ β αAβ ⇒ αγβ αAβαγβ,符号串 γ 仅根据 A 的产生式派生, 而无需依赖 A 的上下文 α 和 β.
  • 如果有两个文法 CFG G1 和 CFG G2,满足L(G1) = L(G2),则称 G1 和 G2 是等价的.
  • 句型
    • C F G G = ( V , T , P , S ) CFG G = (V, T, P, S) CFGG=(V,T,P,S), 初始符号 S 派生出来的符号串, 称为 G 的句型, 即
    • α ∈ ( V ∪ T ) ∗ \alpha \in \left( V \cup T \right)^{*} α(VT) S ⟹ ∗ a S\overset{*}{\Longrightarrow}a Sa
    • 如果 S ⟹ lm ∗ α S\overset{*}{\underset{\text{lm}}{\Longrightarrow}}\alpha Slmα,称 α \alpha α为左句型
    • 如果 S ⟹ rm ∗ α S\overset{*}{\underset{\text{rm}}{\Longrightarrow}}\alpha Srmα,称 α \alpha α为右句型
    • 只含有终结符的句型, 也称为 G 的句子
    • 而 L(G) 就是文法 G 全部的句子

9.3 解析树

CFG G = (V, T, P, S) 的语法分析树(语法树或派生树) 为:

  • 每个内节点标记为 V 中的变元符号;
  • 每个叶节点标记为 V ∪ T ∪ {ε} 中的符号;
  • 如果某内节点标记是 A, 其子节点从左至右分别为X1, X2, · · · , Xn
    • 那么 A → X 1 X 2 ⋅ ⋅ ⋅ X n ∈ P A → X1X2 · · · Xn ∈ P AX1X2XnP
    • 若有 Xi = ε, 则 ε 是 A 唯一子节点, 且 A → ε ∈ P
  • 语法树的全部叶节点从左到右连接起来, 称为该树的产物或结果. 如果树根节点是初始符号 S, 叶节点是终结符或 ε, 那么该树的产物属于 L(G).
  • 语法树中标记为 A 的内节点及其全部子孙节点构成的子树, 称为 A 子树.

例:

CFG G = (V, T, P, S) 且 A ∈ V , 那么文法 G 中

  • A ⟹ ∗ α A\overset{*}{\Longrightarrow}\alpha Aα 当且仅当 G 中存在以 A 为根节点产物为 α 的语法树
  • 每棵语法分析树都有唯一的最左 (右) 派生
  • 给定 CFG G = (V, T, P, S), A ∈ V , 以下命题等价:
    1. 通过递归推理, 确定串 w 在变元 A 的语言中
    2. 存在以 A 为根节点, 产物为 w 的语法分析树
    3. A ⟹ ∗ w A\overset{*}{\Longrightarrow}w Aw
    4. A ⟹ lm ∗ w A\overset{*}{\underset{\text{lm}}{\Longrightarrow}}w Almw
    5. A ⟹ rm ∗ w A\overset{*}{\underset{\text{rm}}{\Longrightarrow}}w Armw

9.4 歧义

有些文法的歧义性, 可以通过重新设计文法来消除

  • 定义同样的语言可以有多个文法, 如果 CFL L 的所有文法都是歧义的,那么称语言 L 是固有歧义的
  • 定义同样的语言可以有多个文法, 如果 CFL L 的所有文法都是歧义的, 那么称语言 L 是固有歧义的.
  • “判定任何给定 CFG G 是否歧义”是一个不可判定问题

10. 上下文无关文法的化简

文法化简的可靠顺序

  1. 消除ε-产生式;
  2. 消除单元产生式;
  3. 消除非产生的无用符号;
  4. 消除非可达的无用符号.

10.1 消除无用符号

  • 无用符号:对文法定义语言没有贡献的符号

  • 初始符号在派生过程中能派生的语言,前后为若干终止符、中间的单一符号为可达的
  • 某一符号和前后的若干终止符能够最终派生为均为终止符的语言,则其是产生的
  • 可达 + 产生 = 有用
  • 非(有用)= 无用 = 非(可达) 或 非(产生)

步骤:

  1. 计算“产生的”符号集
    • 每个 T 中的符号都是产生的
    • A → α ∈ P 且 α 中符号都是产生的, 则 A 是产生的
  2. 计算“可达的”符号集
    • 符号 S 是可达的
    • A → α ∈ P 且 A 是可达的, 则 α 中符号都是可达的
  3. 删除全部含有 “非产生的” 和 “非可达的” 符号的产生式

注:先寻找并消除全部非“产生的”符号,再寻找并消除全部非“可达的”符号,否则可能消除不完整。

  • 例:消除如下文法无用符号
    S → AB | a
    A → b
  • 解:S → bB | a

10.2 消除ε产生式

步骤:

  • 确定“可空变元”
    • 如果 A → ε, 则 A 是可空的
    • 如果 B → α 且 α 中的每个符号都是可空的,则 B 是可空的
  • 确定“可空变元”
    • 将含有可空变元的一条产生式 A → X 1 X 2 ⋅ ⋅ ⋅ X n A → X_1X_2 · · · X_n AX1X2Xn用一组产生式 A → Y 1 Y 2 ⋅ ⋅ ⋅ Y n A → Y_1Y_2 · · · Y_n AY1Y2Yn代替,其中
      • 若 Xi 不是可空的, Yi 为 Xi
      • 若 Xi 是可空的, Yi 为 Xi 或 ε
      • 但 Yi 不能全为 ε (否则A为可空变元)

例:

  • 消除 CFG G = ({S, A, B}, {a, b}, P, S) 的 ε-产生式.
    S → AB
    A → AaA | ε
    B → BbB | ε

解:

  • CFG G′ 为
    S → AB | A | B
    A → AaA | Aa | aA | a
    B → BbB | Bb | bB | b

10.3 消除单元产生式

单元产生式:例如 A → B

步骤:

  • 确定“单元对”
    • 如果有 A ⟹ ∗ B A\overset{*}{\Longrightarrow}B AB, 则称 [ A , B ] [A, B] [A,B] 为单元对
    • A → B ∈ P, 则 [A, B] 是单元对
    • 若 [A, B] 和 [B, C] 都是单元对, 则 [A, C] 是单元对
  • 消除单元产生式
    • 删除全部形为 A → B 的单元产生式
    • 对每个单元对 [A, B], 将 B 的产生式复制给 A

例:

  • 消除文法的单元产生式
    S → A | B | 0S1
    A → 0A | 0
    B → 1B | 1

解:

  • 单位对为 [S, A] 和 [S, B], 带入得:
    S → 0S1
    S → 0A | 0
    S → 1B | 1
    A → 0A | 0
    B → 1B | 1

11. 上下文无关文法的范式

11.1 乔姆斯基范式(CNF)

  • 每个不带 ε 的 CFL 都可以由这样的 CFG G 定义, G 中每个产生式的形式都为 A → B C A → BC ABC A → a A → a Aa
  • 这里的 A, B 和 C 是变元, a 是终结符.
  • 利用 CNF 派生长度为 n 的串, 刚好需要 2n − 1 步

方法:

例:

  • CFG G = ( S , A , B , a , b , P , S ) G = ({S, A, B}, {a, b}, P, S) G=(S,A,B,a,b,P,S), 产生式集合 P 为:
    S → b A ∣ a B S → bA | aB SbAaB
    A → b A A ∣ a S ∣ a A → bAA | aS | a AbAAaSa
    B → a B B ∣ b S ∣ b B → aBB | bS | b BaBBbSb
  • 请设计等价的 CNF 文法.

解:

  • CNF 为:
    S → C b A ∣ C a B S → CbA | CaB SCbACaB
    A → C a S ∣ C b D 1 ∣ a A → C_aS | C_bD_1 | a ACaSCbD1a
    D 1 → A A D1 → AA D1AA
    C a → a C_a → a Caa
    B → C b S ∣ C a D 2 ∣ b B → C_bS | C_aD_2 | b BCbSCaD2b
    D 2 → B B D2 → BB D2BB
    C b → b C_b → b Cbb

11.2 格雷巴赫范式(GNF)

  • 每个不带 ε 的 CFL 都可以由这样的 CFG G 定义, G 中每个产生式的形式都为 A → a α A → aα Aaα
    其中 A 是变元, a 是终结符, α 是零或多个变元的串.
  • GNF 每个产生式都会引入一个终结符
  • 长度为 n 的串的派生恰好是 n 步

例:

  • 将以下文法转换为 GNF.
    S → AB
    A → aA | bB | b
    B → b

解:

  • GNF 为
    S → aAB | bBB | bB
    A → aA | bB | b
    B → b

特殊情况:

  • 直接左递归
  • 间接左递归

12. 下推自动机(PDA)

下推自动机(PDA, Pushdown Automata) P 为七元组
P = ( Q , Σ , Γ , δ , q 0 , Z 0 , F ) P = (Q, Σ, Γ, δ, q_0, Z_0, F) P=(Q,Σ,Γ,δ,q0,Z0,F)

  1. Q Q Q, 有穷状态集;
  2. Σ Σ Σ, 有穷输入符号集;
  3. Γ Γ Γ, 有穷栈符号集;
  4. δ : Q × ( Σ ∪ ε ) × Γ → 2 Q × Γ ∗ δ : Q × (Σ ∪ {ε}) × Γ → 2^{Q×Γ^∗} δ:Q×(Σε)×Γ2Q×Γ, 状态转移函数;
  5. q 0 ∈ Q q0 ∈ Q q0Q, 初始状态;
  6. Z 0 ∈ Γ − Σ Z_0 ∈ Γ − Σ Z0ΓΣ, 栈底符号;
  7. F ⊆ Q F ⊆ Q FQ, 接收状态集或终态集.

例:设计识别 L 01 = { 0 n 1 n ∣ n ≥ 1 } L_{01} = \{0^n1^n | n ≥ 1\} L01={0n1nn1} 的 PDA

例:设计识别 L w w r = { w w R ∣ w ∈ ( 0 + 1 ) ∗ } L_{ww^r} = \{ww^R | w ∈ (0 + 1)^∗\} Lwwr={wwRw(0+1)} 的 PDA

12.1 瞬时描述(ID)

为描述 PDA 瞬间的格局, 定义 Q × Σ ∗ × Γ ∗ Q × Σ^∗ × Γ^∗ Q×Σ×Γ 中三元组
( q , w , γ ) (q, w, γ) (q,w,γ)
为瞬时描述(ID, Instantaneous Description), 表示此时 PDA 处于状态 q q q,
余输入串
w w w, γ γ γ.

12.1.1 转移

在 PDA P P P 中如果 ( p , β ) ∈ δ ( q , a , Z ) (p, β) ∈ δ(q, a, Z) (p,β)δ(q,a,Z), 由 ( q , a w , Z α ) (q, aw, Zα) (q,aw,Zα) ( p , w , β α ) (p, w, βα) (p,w,βα) 的变化, 称为瞬时描述(ID)的转移 ⊢ P ⊢_P P, 记为
( q , a w , Z α ) ⊢ P ( p , w , β α ) (q, aw, Zα) ⊢_P (p, w, βα) (q,aw,Zα)P(p,w,βα)
其中 w ∈ Σ ∗ , α ∈ Γ ∗ w ∈ Σ^∗, α ∈ Γ^∗ wΣ,αΓ.
若有瞬时描述(ID) I I I, J J J K K K, 递归定义 ⊢ P ∗ ⊢^*_P P 为:

  1. I ⊢ P ∗ I I ⊢^*_P I IPI
  2. I ⊢ P ∗ J I ⊢^*_P J IPJ, J ⊢ P ∗ K J ⊢^*_P K JPK,则 I ⊢ P ∗ K I ⊢^*_P K IPK

P P P 已知, 可省略, 记为 ⊢ ⊢ ⊢ ∗ ⊢^* .

例:语言 L 01 = { 0 n 1 n ∣ n ≥ 1 } L_{01} = \{0^n1^n | n ≥ 1\} L01={0n1nn1} 的 PDA, 识别 0011 时的 ID 序列.

解:
( q 0 , 0011 , Z 0 ) ⊢ ( q 0 , 011 , 0 Z 0 ) ⊢ ( q 0 , 11 , 00 Z 0 ) ⊢ ( q 1 , 1 , 0 Z 0 ) ⊢ ( q 1 , ε , Z 0 ) ⊢ ( q 2 , ε , Z 0 ) (q_0, 0011, Z_0) ⊢ (q_0, 011, 0Z_0) ⊢ (q_0, 11, 00Z_0) ⊢ (q_1, 1, 0Z_0) ⊢ (q_1, ε, Z_0) ⊢ (q_2, ε, Z_0) (q0,0011,Z0)(q0,011,0Z0)(q0,11,00Z0)(q1,1,0Z0)(q1,ε,Z0)(q2,ε,Z0)

定理:

  1. ∀ w ∈ Σ ∗ , ∀ γ ∈ Γ ∗ ∀w ∈ Σ^∗, ∀γ ∈ Γ^∗ wΣ,γΓ, 如果
    ( q , x , α ) ⊢ P ∗ ( p , y , β ) , (q, x, α) ⊢^*_P (p, y, β), (q,x,α)P(p,y,β),
    那么
    ( q , x w , α γ ) ⊢ P ∗ ( p , y w , β γ ) (q, xw, αγ) ⊢^*_P (p, yw, βγ) (q,xw,αγ)P(p,yw,βγ)
    即:在可以转移的两个瞬时描述的剩余输入串后加入相同的剩余输入串、栈后加入相同的栈,仍然可以转移;

  2. ∀ w ∈ Σ ∗ ∀w ∈ Σ^∗ wΣ, 如果
    ( q , x w , α ) ⊢ P ∗ ( p , y w , β ) , (q, xw, α) ⊢^*_P (p, yw, β), (q,xw,α)P(p,yw,β),
    那么
    ( q , x , α ) ⊢ P ∗ ( p , y , β ) (q, x, α) ⊢^*_P (p, y, β) (q,x,α)P(p,y,β)
    即:在可以转移的两个瞬时描述的剩余输入串后删除相同的输入串,仍然可以转移;

12.2 下推自动机接受的语言(终态/空栈)

PDA P = ( Q , Σ , Γ , δ , q 0 , Z 0 , F ) P = (Q, Σ, Γ, δ, q_0, Z_0, F) P=(Q,Σ,Γ,δ,q0,Z0,F), 以两种方式接受语言:

  • P 以终态方式接受的语言, 记为 L ( P ) L(P) L(P), 定义为 L ( P ) = w ∣ ( q 0 , w , Z 0 ) ⊢ ∗ ( p , ε , γ ) , p ∈ F . L(P) = {w | (q_0, w, Z_0) ⊢^*(p, ε, γ), p ∈ F}. L(P)=w(q0,w,Z0)(p,ε,γ),pF.
  • P 以空栈方式接受的语言, 记为 N ( P ) N(P) N(P), 定义为 N ( P ) = w ∣ ( q 0 , w , Z 0 ) ⊢ ∗ ( p , ε , ε ) . N(P) = {w | (q_0, w, Z_0) ⊢^*(p, ε, ε)}. N(P)=w(q0,w,Z0)(p,ε,ε).

定理及证明(构造)方法

  • 如果 PDA P F P_F PF 以终态方式接受语言 L,那么一定存在 PDA P N P_N PN 以空栈方式接受 L: P F = ( Q , Σ , Γ , δ F , q 0 , Z 0 , F ) P_F = (Q, Σ, Γ, δ_F, q_0, Z_0, F) PF=(Q,Σ,Γ,δF,q0,Z0,F) 构造 P N = ( Q ∪ { p 0 , p } , Σ , Γ ∪ { X 0 } , δ N , p 0 , X 0 , ∅ ) P_N = (Q ∪ \{p_0, p\}, Σ, Γ ∪ \{X0\}, δ_N, p_0, X_0, ∅) PN=(Q{p0,p},Σ,Γ{X0},δN,p0,X0,)
    终止状态时,空转移到 p p p、弹栈栈底符号
  • 反之亦然: P N = ( Q , Σ , Γ , δ N , q 0 , Z 0 , ∅ ) P_N = (Q, Σ, Γ, δ_N, q_0, Z_0, ∅) PN=(Q,Σ,Γ,δN,q0,Z0,) 构造 P F = ( Q ∪ { p 0 , p f } , Σ , Γ ∪ { X 0 } , δ F , p 0 , X 0 , { p f } ) P_F = (Q ∪ \{p_0, p_f\}, Σ, Γ ∪ \{X_0\}, δ_F, p_0, X_0, \{p_f\}) PF=(Q{p0,pf},Σ,Γ{X0},δF,p0,X0,{pf})
    空栈时,空转移到新建的终止状态 p f p_f pf

例1:识别 L w w r L_{ww^r} Lwwr 的 PDA P P P , 从终态方式接受, 改为空栈方式接受.

  • 解:
    δ ( q 1 , ε , Z 0 ) = { ( q 1 , ε ) } δ(q_1, ε, Z_0) = \{(q_1, ε)\} δ(q1,ε,Z0)={(q1,ε)} 代替 δ ( q 1 , ε , Z 0 ) = { ( q 2 , Z 0 ) } δ(q_1, ε, Z_0) = \{(q_2, Z_0)\} δ(q1,ε,Z0)={(q2,Z0)} 即可

例2:接受 L = { w ∈ { 0 , 1 } ∗ ∣ w 中 字 符 0 和 1 的 数 量 相 同 } L = \{w ∈ \{0, 1\}^∗ | w 中字符 0 和 1 的数量相同\} L={w{0,1}w01} 的 PDA

  • 栈空时,压栈;
  • 栈不空时:
    • 若输入符与栈顶相同,压栈;
    • 若输入符与栈顶不同,弹栈;
  • 栈空为接受状态。

例3:接受 L = { 0 n 1 m ∣ 0 ≤ n ≤ m ≤ 2 n } L = \{0^n1^m | 0 ≤ n ≤ m ≤ 2n\} L={0n1m0nm2n} 的 PDA

  • 定义:左、中、右、下4个状态
  • 左状态:读入0(自身递归转移)
    • 转移到中状态:空转移(栈中有0或无0都可)
  • 中状态:读入1
    • 转移到下状态:(栈中有至少一个0,至少连续2个1)读入一个1,不弹栈
    • 下状态转移回来:再读入一个1,弹栈
    • 和下状态的一个来回读入2个1
    • 自身转移:当1的个数是奇数
  • 右状态:空栈,结束

13. CFG ⟺ \Longleftrightarrow PDA(等价性)

13.1 CFG ⟹ \Longrightarrow PDA

例:设计语言 L = { 0 n 1 m ∣ 1 ≤ m ≤ n } L = \{0^n1^m | 1 ≤ m ≤ n\} L={0n1m1mn} 的 PDA,并转换为CFG
解:

  • PDA:
  • CFG G:
    S → A B S → AB SAB
    A → 0 A ∣ ε A → 0A | ε A0Aε
    B → 0 B 1 ∣ 01 B → 0B1 | 01 B0B101

  • 字符串 00011 的最左派生:
    S ⟹ l m A B ⟹ l m 0 A B ⟹ l m 0 B ⟹ l m 00 B 1 ⟹ l m 00011 S \underset{lm}{\Longrightarrow} AB \underset{lm}{\Longrightarrow} 0AB \underset{lm}{\Longrightarrow} 0B \underset{lm}{\Longrightarrow} 00B1 \underset{lm}{\Longrightarrow} 00011 SlmABlm0ABlm0Blm00B1lm00011

用 PDA 栈顶符号的替换, 模拟文法的最左派生

  • 栈顶为变元:输入 ε ε ε,变元派生(如: ε , S → 0 S 1 ε, S → 0S1 ε,S0S1
  • 栈顶为终结符:输入非空字符,输入串减少,栈顶弹出
  • 例解:

13.2 PDA ⟹ \Longrightarrow CFG

如果 PDA P = ( Q , Σ , Γ , δ , q 0 , Z 0 , ∅ ) P = (Q, Σ, Γ, δ, q_0, Z_0, ∅) P=(Q,Σ,Γ,δ,q0,Z0,), 那么构造 CFG G = ( V , Σ , P ′ , S ) G = (V, Σ, P^′, S) G=(V,Σ,P,S), 其中
V V V P ′ P^′ P

  1. V = { [ q X p ] ∣ p , q ∈ Q , X ∈ Γ } ∪ { S } V = \{[qXp] | p,q ∈Q, X ∈ Γ\} ∪ \{S\} V={[qXp]p,qQ,XΓ}{S};
  2. ∀ p ∈ Q ∀p ∈ Q pQ, 构造产生式 S → [ q 0 Z 0 p ] S → [q_0Z_0p] S[q0Z0p];
  3. ∀ ( p , Y 1 Y 2 ⋅ ⋅ ⋅ Y n ) ∈ δ ( q , a , X ) ∀(p, Y_1Y_2 · · · Y_n) ∈ δ(q, a, X) (p,Y1Y2Yn)δ(q,a,X), 构造 ∣ Q ∣ n |Q|n Qn 个产生式
    [ q X r n ] → a [ p Y 1 r 1 ] [ r 1 Y 2 r 2 ] ⋅ ⋅ ⋅ [ r n − 1 Y n r n ] [qXr_n] → a[pY_1r_1][r_1Y_2r_2] · · · [r_{n−1}Y_nr_n] [qXrn]a[pY1r1][r1Y2r2][rn1Ynrn]
    其中 a ∈ Σ ∪ { ε } a ∈ Σ ∪ \{ε\} aΣ{ε}, X , Y i ∈ Γ X,Y_i ∈ Γ X,YiΓ, 而 r i ∈ Q r_i ∈ Q riQ n n n ∣ Q ∣ |Q| Q 种状态的组合; 若 i = 0 i = 0 i=0, 为 [ q X p ] → a [qXp] → a [qXp]a.

简单记忆

  • δ ( a , b , c ) = ( d , e f ) \delta(a, b, c)=(d, e f) δ(a,b,c)=(d,ef) 转换为 [ a c r 2 ] → b [ d e r 1 ] [ r 1 f r 2 ] [acr_2]\rightarrow b[der_1][r_1fr_2] [acr2]b[der1][r1fr2]
  • δ ( a , b , c ) = ( d , e ) \delta(a, b, c)=(d, e) δ(a,b,c)=(d,e) 转换为 [ a c r 1 ] → b [ d e r 1 ] [acr_1]\rightarrow b[der_1] [acr1]b[der1]
  • δ ( a , b , c ) = ( d , ε ) \delta(a, b, c)=(d, ε) δ(a,b,c)=(d,ε) 转换为 [ a c d ] → b [acd]\rightarrow b [acd]b
  • 最后用有穷状态集带入 r 1 r 2 r_1 r_2 r1r2

例:将 PDA P = ({p, q}, (0, 1), {X, Z}, δ, q, Z) 转为 CFG, 其中 δ 如下:

解:

化简:

14. GNF ⟹ \Longrightarrow PDA

如果 GNF 格式的 CFG G = ( V , T , P ′ , S ) G = (V, T, P^′, S) G=(V,T,P,S), 那么构造 PDA
P = ( { q } , T , V , δ , q , S , ∅ ) P = (\{q\}, T, V, δ, q, S, ∅) P=({q},T,V,δ,q,S,)
为每个产生式, 定义 δ 为:
δ ( q , a , A ) = { ( q , β ) ∣ A → a β ∈ P ′ } δ(q, a, A) = \{(q, β) | A → aβ ∈ P^′\} δ(q,a,A)={(q,β)AaβP}

即:每次读入终结符,将栈中变元进行派生(弹栈+压栈),直到栈中均为终结符。

例:文法 S → a A A , A → a S ∣ b S ∣ a S → aAA, A → aS | bS | a SaAA,AaSbSa 为 GNF 格式, 构造等价的 PDA

15. 确定性下推自动机(DPDA)

如果 PDA P = ( Q , Σ , Γ , δ , q 0 , Z 0 , F ) P = (Q, Σ, Γ, δ, q_0, Z_0, F) P=(Q,Σ,Γ,δ,q0,Z0,F) 满足

  1. ∀ a ∈ Σ ∪ { ε } ∀a ∈ Σ ∪ \{ε\} aΣ{ε}, δ ( q , a , X ) δ(q, a, X) δ(q,a,X) 至多有一个动作;
  2. ∀ a ∈ Σ ∀a ∈ Σ aΣ, 如果 δ ( q , a , X ) ≠ ∅ δ(q, a, X) \neq ∅ δ(q,a,X)=, 那么 δ ( q , ε , X ) = ∅ . δ(q, ε, X) = ∅. δ(q,ε,X)=.

∀ ( q , a , Z ) ∈ Q × Σ × Γ ∀(q, a, Z) ∈ Q × Σ × Γ (q,a,Z)Q×Σ×Γ 满足 ∣ δ ( q , a , Z ) ∣ + ∣ δ ( q , ε , Z ) ∣ ≤ 1 |δ(q, a, Z)| + |δ(q, ε, Z)| ≤ 1 δ(q,a,Z)+δ(q,ε,Z)1
即:每一个瞬时描述下至多有一个转移状态(可以无动作)

则称 P P P 为确定型下推自动机(DPDA)

  • DPDA P P P终态方式接受的语言 L ( P ) L(P) L(P) 称为确定性上下文无关语言(DCFL)

  • 注:DPDA 与 PDA 不等价

例:任何 DPDA 都无法接受 L w w r L_{ww^r} Lwwr, 但是可以接受
L w c w r = { w c w R ∣ w ∈ ( 0 + 1 ) ∗ } L_{wcw^r} = \{wcw^R | w ∈ (0 + 1)^∗\} Lwcwr={wcwRw(0+1)}
设计DPDA

DCFL 的重要应用

  • 非固有歧义语言的真子集
  • 程序设计语言的语法分析器
  • LR(k) 文法, Yacc 的基础, 解析时间复杂度为 O(n)
  • 如果 L L L 是正则语言, 那么存在 DPDA P P P 以终态方式接受 L L L, 即 L = L ( P ) L = L(P) L=L(P)
  • 证明: 显然,DPDA P P P 可以不用栈而模拟任何 DFA。
  • 结论: 正 则 语 言 ⊆ D C F L ⊆ C F L 正则语言 ⊆ DCFL ⊆ CFL DCFLCFL

  • 前缀性质:如果语言 L 中不存在字符串 x 和 y, 使 x 是 y 的前缀, 称语言 L 满足前缀性质.
  • DPDA P P P L = N ( P ) L = N(P) L=N(P), 当且仅当 L L L 有前缀性质, 且存在 DPDA P ′ P^′ P 使 L = L ( P ′ ) L = L(P ′) L=L(P).
  • DPDA P P P N ( P ) N(P) N(P) 更有限, 即使正则语言 0 ∗ 0^∗ 0 也无法接受
  • 但却可以被某个 DPDA 以终态方式接受

DPDA 与歧义文法

DPDA P P P, 语言 L = L ( P ) L = L(P) L=L(P), 那么 L L L 有无歧义的 CFG

  • 因此 DPDA 在语法分析中占重要地位
  • 但是并非所有非固有歧义 CFL 都会被 DPDA 识别
    L w w r L_{ww^r} Lwwr有无歧义文法 S → 0 S 0 ∣ 1 S 1 ∣ ε S → 0S0 | 1S1 | ε S0S01S1ε

16 上下文无关语言的泵引理

如果语言 L L L 是 CFL, 那么存在正整数 N N N, 对 ∀ z ∈ L ∀z ∈ L zL,
只要 ∣ z ∣ ≥ N |z| ≥ N zN, 就可以将 z z z 分为五部分 z = u v w x y z = uvwxy z=uvwxy 满足:

  1. v x ≠ ε vx \neq ε vx=ε (或 ∣ v x ∣ > 0 |vx| > 0 vx>0);
  2. ∣ v w x ∣ ≤ N |vwx| ≤ N vwxN;
  3. ∀ i ≥ 0 , u v i w x i y ∈ L ∀i ≥ 0, uv^iwx^iy ∈ L i0,uviwxiyL.

例:证明 L = { 0 n 1 n 2 n ∣ n ≥ 1 } L = \{0^{n}1^{n}2^{n} | n ≥ 1\} L={0n1n2nn1} 不是上下文无关语言

解:

  1. 假设 L L L 是 CFL, 那么存在整数 N, 对 ∀ z ∈ L ( ∣ z ∣ ≥ N ) ∀z ∈ L (|z| ≥ N) zL(zN) 满足泵引理.
  2. L L L 中取 z = 0 N 1 N 2 N z = 0^N1^N2^N z=0N1N2N, 则显然 z ∈ L z ∈ L zL ∣ z ∣ = 3 N ≥ N |z| = 3N ≥ N z=3NN.
  3. 由泵引理, z z z 可被分为 z = u v w x y z = uvwxy z=uvwxy, 且有 ∣ v w x ∣ ≤ N |vwx| ≤ N vwxN v x ≠ ε vx \neq ε vx=ε.
  4. 那么 v w x vwx vwx 可能
    • 只包含 0, 1 或 2, 那么 u w y ∉ L uwy \notin L uwy/L;
    • 只包含 0 和 1, 或只包含 1 和 2, 那么也有 u w y ∉ L uwy \notin L uwy/L;
  5. 与泵引理 u w y = u v 0 w x 0 y ∈ L uwy = uv_0wx_0y ∈ L uwy=uv0wx0yL 矛盾, 假设不成立.
  6. L L L 不是上下文无关的

例:证明 L = { w w ∣ w ∈ 0 , 1 ∗ } L = \{ww | w ∈ {0, 1}^∗\} L={www0,1} 不是上下文无关的

(错误的) 证明: 假设 L L L 是 CFL. 取 z = 0 N 1 0 N 1 z = 0^N10^N1 z=0N10N1, 那么 z = u v w x y z = uvwxy z=uvwxy

则对任意 i ≥ 0 i ≥ 0 i0, 有 u v i w x i y ∈ L uv^iwx^iy ∈ L uviwxiyL, 满足泵引理.

(正确的) 证明: 假设 L L L 是 CFL. 取 z = 0 N 1 N 0 N 1 N z = 0^N1^N0^N1^N z=0N1N0N1N, 将 z z z 分为 z = u v w x y z = uvwxy z=uvwxy

  1. v w x vwx vwx z z z 中点的一侧, u v 0 w x 0 y uv_0wx_0y uv0wx0y 显然不可能属于 L L L;
  2. v w x vwx vwx 包括 z z z 中点, 那么 u v 0 w x 0 y uv_0wx_0y uv0wx0y 0 N 1 i 0 j 1 N 0^N1^i0^j1^N 0N1i0j1N, 也不可能属于 L L L.
    所以假设不成立, L L L 不是 CFL

17 上下文无关语言的封闭性

封闭

  • 连接
  • 闭包
  • 同态
  • 逆同态
  • 反转

不封闭

  • 补运算

17.1 代换

两个字母表 Σ \Sigma Σ Γ \Gamma Γ 的函数 s   :   Σ   → 2 Γ ∗ s\ :\ \Sigma\ \rightarrow 2^{\Gamma^{*}} s : Σ 2Γ 称为代换. Σ \Sigma Σ 中的一个字符 a a a s s s 的作用下为
Γ \Gamma Γ 上的一个语言 L a L_{a} La, 即

s ( a )   =   L a s(a)\ = \ La s(a) = La

扩展 s s s 的定义到字符串,

s ( ε )   =   ε s(\varepsilon)\ = \ \varepsilon s(ε) = ε

s ( x a )   =   s ( x ) s ( a ) s(xa)\ = \ s(x)s(a) s(xa) = s(x)s(a)

再扩展 h h h 到语言, 对 ∀ L  ⊆   Σ ∗ \forall\text{L\ } \subseteq \ \Sigma^{*}  Σ

s ( L )   =   ⋃ x ∈ L s ( x ) s(L)\ = \ \bigcup_{x \in L}^{}{s(x)} s(L) = xLs(x)

  • 定理:如果有 Σ Σ Σ 上的 CFL L L L 和代换 s s s, 且每个 a ∈ Σ a ∈ Σ aΣ s ( a ) s(a) s(a) 都是 CFL, 那么 s ( L ) s(L) s(L) 也是 CFL

  • 即:可以把CFL的每个终结符扩展为一个CFL,生成的语言还是CFL

具体构造方法:

设 CFL L L L 的文法 G   =   ( V ,   T ,   P ,   S ) G\ = \ (V,\ T,\ P,\ S) G = (V, T, P, S), 每个 s ( a ) s(a) s(a) 的文法 G a =   ( V a ,   T a ,   P a ,   S a ) G_{a} = \ (V_{a},\ T_{a},\ P_{a},\ S_{a}) Ga= (Va, Ta, Pa, Sa).

那么 s ( L ) s(L) s(L) 的文法可以构造为

G ′   =   ( V   ′ ,   T   ′ ,   P   ′ ,   S )   G'\ = \ (V\ ',\ T\ ',\ P\ ',\ S)\ G = (V , T , P , S) 

  1. V ′ = V ∪ ( ⋃ a ∈ T V a   ) V^{'}=V \cup (\bigcup_{a \in T}^{}V_{a}\ ) V=V(aTVa )

  2. T ′ = ⋃ a ∈ T T a T^{'}=\bigcup_{a \in T}^{}T_{a} T=aTTa

  3. P ′ P^{'} P包括每个 P a P_{a} Pa P P P 中产生式,但是要将 P P P的产生式中每个终结符 a a a均替换为文法 G a G_{a} Ga 的开始符号 S a S_{a} Sa.

17.2 封闭性应用

例: 请证明语言 L L L 不是 CFL L = { w ∈ { a , b , c } ∗ ∣ n a ( w ) = n b ( w ) = n c ( w ) } L = \{w ∈ {\{a, b, c\}}^∗ | n_a(w) = n_b(w) = n_c(w)\} L={w{a,b,c}na(w)=nb(w)=nc(w)},其中 n a ( w ) n_a(w) na(w) 表示 w w w a a a 的个数.

证明:

  1. 因为 a ∗ b ∗ c ∗ a^∗b^∗c^∗ abc 是正则语言,
  2. L ∩ a ∗ b ∗ c ∗ = { a n b n c n ∣ n ≥ 0 } L ∩ a^∗b^∗c^∗ = \{a^nb^nc^n | n ≥ 0\} Labc={anbncnn0} 不是 CFL,
  3. 由 CFL 与正则语言的交还是 CFL, 所以 L L L 不可能是 CFL

18 上下文无关语言的判定性质

18.1 可判定的 CFL 问题

空性: 只需判断文法的开始符号 S 是否为非产生的
有穷性和无穷性:

  1. 用不带无用符号的 CNF 的产生式画有向图;
  2. 变元为顶点, 若有 A → BC, 则 A 到 B 和 C 各画一条有向边;
  3. 检查图中是否有循环.

成员性: 利用 CNF 范式, 有CYK算法检查串 w 是否属于 L

18.2 CYK算法

例:CNF G G G 如下, 用 CYK 算法判断 b b a b a a ∈ L ( G ) bbabaa ∈ L(G) bbabaaL(G)?

解:

S → A B ∣ B C S → AB | BC SABBC
A → B A ∣ a A → BA | a ABAa
B → C C ∣ b B → CC | b BCCb
C → A B ∣ a C → AB | a CABa

  • 填写最下层(单个终结符是否有可达)

  • 计算上面若干行


  • 结果

  • 因为 S ∈ X 16 = { S , A } S ∈ X_{16} = \{S, A\} SX16={S,A}, 所以 b b a b a a ∈ L ( G ) bbabaa ∈ L(G) bbabaaL(G)

18.3 不可判定的 CFL 问题

  1. 判断 CFG G G G 是否歧义的?
  2. 判断 CFL 是否固有歧义的?
  3. 两个 CFL 的交是否为空?
  4. 两个 CFL 是否相同?
  5. 判断 CFL 的补是否为空? 尽管有算法判断 CFL 是否为空
  6. 判断 CFL 是否等于 Σ ∗ Σ^∗ Σ?

19. 图灵机

FA PDA TM
( Q Q Q, Σ \Sigma Σ, δ \delta δ, q 0 q_0 q0, F F F) ( Q Q Q, Σ \Sigma Σ, Γ \Gamma Γ, δ \delta δ, q 0 q_0 q0, z 0 z_0 z0, F F F) ( Q Q Q, Σ \Sigma Σ, Γ \Gamma Γ, δ \delta δ, q 0 q_0 q0, B B B, F F F)
  • 图灵机(TM, Turing Machine) M M M 为七元组
    M = ( Q , Σ , Γ , δ , q 0 , B , F ) M = (Q,\Sigma,\Gamma,\delta,q_0,B,F) M=(Q,Σ,Γ,δ,q0,B,F)
  1. Q Q Q: 有穷状态集;
  2. Σ Σ Σ: 有穷输入符号集;
  3. Γ Γ Γ: 有穷带符号集, 且总有 Σ ⊂ Γ Σ ⊂ Γ ΣΓ;
  4. δ : Q × Γ → Q × Γ × { L , R } δ: Q × Γ → Q × Γ × \{L, R\} δ:Q×ΓQ×Γ×{L,R} 转移函数;
  5. q 0 ∈ Q q_0 ∈ Q q0Q: 初始状态;
  6. B ∈ Γ − Σ B ∈ Γ − Σ BΓΣ: 空格符号;
  7. F ⊆ Q F ⊆ Q FQ: 终态集或接受状态集.

与有穷自动机区别:

  • 可修改(必须修改,但可以相同)
  • 可向左或向右移动输入带
  • 有空格符号

例:设计识别 { 0 n 1 n ∣ n ≥ 1 } \{0^n1^n | n ≥ 1\} {0n1nn1} 的图灵机

解:

  • 每次标记一个0和一个1
  • 标记0为X(X=“0已标记”)之后,越过所有未标记的0和已标记的1,将1标记为Y(Y=“1已标记”)
  • 无未标记1后向右找到空格B,结束

M = ( { q 0 , q 1 , q 2 , q 3 , q 4 } , { 0 , 1 } , { 0 , 1 , X , Y , B } , δ , q 0 , B , { q 4 } ) M = (\{q0, q1, q2, q3, q4\}, \{0, 1\}, \{0, 1, X, Y, B\}, δ, q_0, B, \{q4\}) M=({q0,q1,q2,q3,q4},{0,1},{0,1,X,Y,B},δ,q0,B,{q4})

19.1 瞬时描述(ID)

图灵机虽有无穷长的带, 但经过有限步, 带上非空内容总是有限的. 因此用全部非空符号、当前状态及带头位置, 定义图灵机的瞬时描述(ID)为
X 1 X 2 ⋅ ⋅ ⋅ X i − 1 q X i X i + 1 ⋅ ⋅ ⋅ X n X_1X_2 · · · X_{i−1}qX_iX_{i+1} · · · X_n X1X2Xi1qXiXi+1Xn

  1. 图灵机的当前状态 q q q
  2. 带头在左起第 i i i 个非空格符 X i X_i Xi
  3. X 1 X 2 ⋅ ⋅ ⋅ X n X_1X_2 · · · X_n X1X2Xn是最左到最右非空格内容

如果 δ ( q , X i ) = ( p , Y , L ) δ(q, Xi) = (p, Y, L) δ(q,Xi)=(p,Y,L), 定义 ID 转移为
X 1 ⋅ ⋅ ⋅ X i − 1 q X i ⋅ ⋅ ⋅ X n ⊢ X 1 ⋅ ⋅ ⋅ X i − 2 p X i − 1 Y X i + 1 ⋅ ⋅ ⋅ X n X_1 · · · X_{i−1}qX_i · · · X_n ⊢ X_1 · · · X_{i−2}pX_{i−1}YX_{i+1} · · · X_n X1Xi1qXiXnX1Xi2pXi1YXi+1Xn

续例:设计识别 { 0 n 1 n ∣ n ≥ 1 } \{0^n1^n | n ≥ 1\} {0n1nn1} 的图灵机, 接受 0011 的 ID 序列

解:
q 00011 ⊢ X q 1011 ⊢ X 0 q 111 ⊢ X q 20 Y 1 ⊢ q 2 X 0 Y 1 ⊢ X q 00 Y 1 ⊢ X X q 1 Y 1 ⊢ X X Y q 11 ⊢ X X q 2 Y Y ⊢ X q 2 X Y Y ⊢ X X q 0 Y Y ⊢ X X Y q 3 Y ⊢ X X Y Y q 3 B ⊢ X X Y Y B q 4 B q00011 ⊢ Xq1011 ⊢ X0q111 ⊢ Xq20Y1 ⊢ q2X0Y1 ⊢ Xq00Y1 ⊢ XXq1Y1 ⊢ XXYq11 ⊢ XXq2Y Y ⊢ Xq2XYY ⊢ XXq0YY ⊢ XXYq3Y ⊢ XXYYq3B ⊢ XXYYBq4B q00011Xq1011X0q111Xq20Y1q2X0Y1Xq00Y1XXq1Y1XXYq11XXq2YYXq2XYYXXq0YYXXYq3YXXYYq3BXXYYBq4B

19.2 递归可枚举语言

如果 M 是一个图灵机,则 M 接受的语言为
L ( M ) = { w ∣ w ∈ Σ ∗ , q 0 w ⊢ ∗ α p β , p ∈ F , α , β ∈ Γ ∗ } L(M) = \{w | w ∈ Σ^∗, q_0w ⊢*αpβ, p ∈ F, α, β ∈ Γ^∗\} L(M)={wwΣ,q0wαpβ,pF,α,βΓ}

如果 L L L 是图灵机 $M $的语言, 即 L = L ( M ) L = L(M) L=L(M), 则称 L L L递归可枚举语言.

一般假定, 当输入串被接受时, 图灵机总会停机
然而, 对于不接受的输入, 图灵机可能永远不停止

对接受和不接受的输入, 都保证停机的图灵机, 所接受的语言称为递归语言

19.3 真减法

例:Compute the function nomus (m, n)=max(m-n,0)

解:

  • put 1m01n into tape as input
  • delete a 1 from 1m and a 1 from 1n

19.4 乘法

例:Construct a TM to compute m×n

3 × 2 = 2 + 2 + 2

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

形式语言与自动机总结笔记 的相关文章

  • Java对正则表达式的支持(手机、身份证校验)

    目录 1 数量 单个 字符匹配 2 数量 单个 字符集 可以从里面任选一个字符 3 数量 单个 简化字符集 4 边界匹配 5 数量表示 默认情况下只有添加上了数量单位才可以匹配多位字符 6 逻辑表达式 可以连接多个正则 7 理解字符 的含义
  • 三款记事本替代工具 哪个最好用?

    三款记事本替代工具 哪个最好用 http www sina com cn 2008年08月27日 08 35 IT168 com Windows操作系统中自带了不少的实用小程序 但是它们大都功能简陋 有时无法满足我们的使用 此外还有一些Wi
  • 离散数学 --- 命题逻辑 -- 命题符号化与命题公式

    第一部分 命题符号化及其应用 1 等价连接词中 P Q同为真同为假时为真 真假不同时为假 下面是各个联结词的真值表 复合命题的真值只取决于通过联结词构成他的简单命题的真值 与简单命题的内容无关 比如 中国在地球上且太阳东升西落 这是一个复合
  • Day 13 - 正则表达式习题

    利用正则表达式完成下面的操作 1 用户名匹配 要求 1 用户名只能包含数字 字母 下划线 2 不能以数字开头 3 度在 6 到 16 位范围内 re username re compile r a zA Z w 5 15 print re
  • Web前端复习——JS(正则表达式+内置对象)

    正则表达式 专门规定字符中字符 格式规则 的表达式 何时使用 只要定义字符串格式规则 都用正则表达式 最简单正则 一个关键词的原文 就是最简单的正则 1 备选字符集 规定某 一位 字符可选的备选文字列表 语法 备选字符列表 强调 1 无论备
  • Linux文本处理工具和正则表达式

    Linux文本处理工具和正则表达式 一 查看 截取和修改文本的工具 1 查看文本的工具 cat 最常用的文件查看命令 当不指明文件或者文件名为一杠 时 读取标准输入 cat OPTION FILE A 显示所有控制符 tab键 I 行结束符
  • JavaScript最后分水岭——正则表达式

    个人简介 个人主页 微风洋洋 博客领域 编程基础 后端 写作风格 干货 干货 还是tmd的干货 精选专栏 JavaScript 支持洋锅 点赞 收藏 留言 好久不见 甚是想念 大家好 我是微风洋洋 也可以叫我洋锅 细心地小伙伴可能已经发现
  • 主合取/析取范式

    前置知识 简单合取 析取式 合取 析取范式 极小项 当存在n个命题变项做合取时 如果这个简单合取式出现了全部的命题变项或它的否定形式 且恰好只出现一次 则这个式子属于极小项 以n 3 命题变项为p q r为例 他们的极小项如表 主析取范式
  • Java正则表达式详解

    1 1 正则表达式的概念以及演示 正则表达式可以用一些规定的字符来制定规则 并用来校验数据格式的合法性 正则表达式就是用来验证各种字符串的规则 它内部描述了一些规则 我们可以验证用户输入的字符串是否匹配这个规则 正则表达式是一种强大的校验机
  • 用Requests和正则表达式爬取猫眼电影(TOP100+最受期待榜)

    目标站点分析 目标站点 猫眼榜单TOP100 如下图 猫眼电影的翻页offset明显在URL中 所以只要搞定第一页的内容加上一个循环加上offset就可以爬取前100 流程框架 1 抓取单页内容 利用requests请求目标站点 得到单个网
  • test is not a function (js正则表达式匹配问题)

    js中正则表达式匹配时 如果使用test函数 就必须不带引号 并且必须是 定义的规则变量 test 要测试的string 定义变量规则不要带引号 会错误的 如果不使用test 使用match则可以带引号 var re 1 9 d 4 10
  • 空格的正则表达式

    在正则表达式想使用空格的时候不能采用 s的方法 因为 s指的是空白 就是所有空白 如果想表示单纯的空格的话可以采用 方括号本身就是匹配其中的字符 那么其中放空格就是匹配空格 如果有其他正则表达式问题可以查看 https blog csdn
  • Python命令行参数定义及注意事项

    在命令行中运行python代码是很常见的 下面介绍如何定义命令后面跟的参数 常规用法 Python代码中主要使用下面几行代码来定义并获取需要在命令行中赋值的参数 import argparse parser argparse Argumen
  • js正则表达式多行匹配

    在js匹配网页内容时 往往需要匹配一段代码比如 div div 中间可能有很多行 这个时候一般 的匹配规则是匹配不出来的 如下介绍一个折中的方法 var content 这里是内容 var re p class s S p gt g var
  • 元字符的详细解析

    上一篇文章介绍了正则的用处以及正则中这些元字符的基本含义 但是如果我们只知道那些元字符的含义 不知道怎么使用和加以练习 那么对于正则我们还只是看见了门槛 并没有踏入 那么本篇文章就让我们迈起脚步正式走入正则的世界吧 let s go 我的学
  • C#中Validating和Validated事件

    您可能经常需要检查用户输入到 Windows 窗体中的信息是否有效 例如 如果您有一个电话号码的 TextBox 控件 则可以检查该控件是否只包含适当的字符 数字 括号和连字符等等 通常 可使用正则表达式验证用户输入的数据 了解Valida
  • JS字符串替换函数全部替换方法

    color olive JS字符串替换函数 Replace 字符串1 字符串2 1 我们都知道JS中字符串替换函数是Replace 字符串1 字符串2 但是这个函数只能将第一次出现的字符串1替换掉 那么我们如何才能一次性全部替换掉了 将上面
  • Python进阶之CrawlSpider的应用及Scrapy配置项的引用

    1 CrawlSpider的应用 CrawlSpider可以根据规则自动分析链接的数据并按照正则的要求取出需要的数据 scrajpy startproject yg cd yg 注意 t crawl参数 scrapy genspider t
  • -离散数学-期末练习题解析

    一 选择题 二 填空题 三 计算题 四 简答题 五 证明题 六 应用题 一 选择题 下列句子中 是命题 A 2是常数 B 这朵花多好看啊 C 请把们关上 D 下午有会吗 A 命题是能判断真假的陈述句 B是感叹句 C是祈使句 D是疑问句 令p
  • grep的用法

    命令介绍 Linux系统中grep命令是一种强大的文本搜索工具 它能使用正则表达式搜索文本 并把匹配的行打印出来 匹配到的标红grep全称是Global Regular Expression Print 表示全局正则表达式版本 它的使用权限

随机推荐