2DFA和DFA的等价性

本文转自我原来的洛谷博客

这是大一下学期某次计科导的思考题把这个问题拿来给大一学生思考真是很难想象开课老师的精神状态

首先吐槽一句资料真的难找。网上有关这方面的资料少之又少,顶多介绍了2DFA\text{2DFA}的定义和结论,但是没有给出2DFA\text{2DFA}DFA\text{DFA}的等价性证明的。为了填补国内对于这一问题的资料的空白,我决定写这么一篇文章把这个问题讲清楚。

根据目前资料来看,这个成果最早见于上古时期1959年的一篇论文《Finite Automata and Their Decision Problems》\text{《Finite Automata and Their Decision Problems》}中,作者是M.Rabin\text{M.Rabin}Dana Scott\text{Dana Scott}。两位因此获得了1976年的图灵奖。当然我刚开始去找的时候发现这篇论文没地方白嫖,购买要33刀太贵了。

现在的计算理论教材介绍这个内容的貌似很少了,主要原因可能是原始论文中的构造过于复杂。但是这里要感谢神通广大的计算理论老师给我提供了一份1979年“计算理论早期的一本标准参考书” Introduction to Automata Theory第一版(第二版,第三版太简单了)英文原版(中译本有,但是很难找到了)djvu影印版本(pdf版没找到),作者是John.E.Hopcroft\text{John.E.Hopcroft}Jeffrey.D.Ullman\text{Jeffrey.D.Ullman},算是本上古奇书。这篇文章的内容基本全部翻译自原书的2.6节。

感谢vfk给了一份原始论文虽然我不知道他是怎么找到的,也还没怎么看

1.前置\text{1.前置}

2DFA\text{2DFA}的定义网上都能找到,这里不多说,符号基本上也是全世界通用的。2DFA\text{2DFA}的五元组定义中与DFA\text{DFA}唯一的不同是2DFA\text{2DFA}δ\delta定义为Q×ΣQ×{L,R}Q\times \Sigma \to Q\times\{L,R\}

在描述DFA\text{DFA}的行为的时候,我们将δ\delta函数的定义域扩展至了Q×ΣQ\times \Sigma^\ast,用以描述DFA\text{DFA}从某个状态出发接受一个字符串以后到达的状态。但是对于2DFA\text{2DFA}这种技巧不再奏效,因为是可以向左移动的。

我们定义2DFA\text{2DFA}格局IΣQΣ\text{I}\in \Sigma^\ast Q \Sigma^\astI\text{I}可写作wqxwqxw,xΣ,qQw,x\in \Sigma^\ast, q\in Q。代表含义如下:

  1. wxwx是输入串

  2. $ q $是当前状态

  3. 2DFA\text{2DFA}的读入端正在读取xx的第一个字符

特别的,x=ϵx=\epsilon表示2DFA\text{2DFA}的读入端已经移出了输入串的右边界。

我们定义二元关系 M\vdash_MI1MI2I_1 \vdash_M I_2当且仅当通过读入端的一次移动可以格局I1I_1转移至格局I2I_2

我们由此可以对M\vdash_M(以下简记作\vdash)给出形式化的定义:

  1. a1a2...ai1qai...ana1a2...ai1aipai+1...an,whenever δ(q,ai)=(p,R)a_1a_2...a_{i-1}qa_i...a_n\vdash a_1a_2...a_{i-1}a_ipa_{i+1}...a_n,\text{whenever } \delta(q,a_i)=(p,R)

  2. a1a2...ai2ai1qai...ana1a2...ai2pai1ai...an,whenever δ(q,ai)=(p,L)a_1a_2...a_{i-2}a_{i-1}qa_i...a_n \vdash a_1a_2...a_{i-2}pa_{i-1}a_i...a_n,\text{whenever } \delta(q,a_i)=(p,L)

i>1i>1防止移出左端,而i=n+1i=n+1时没有可用的移动。

我们定义 $\vdash^\ast \vdash$的传递闭包。利用上面的记号我们就可以写出 2DFA\text{2DFA} MM接受的语言L(M)L(M)的形式化定义: L(M)={wq0wwp,pF}L(M)=\{w|q_0w \vdash^\ast wp,p\in F\}

2.crossing sequence\text{2.crossing sequence}

对于2DFA\text{2DFA}的行为的一个有用的描述是读取输入时读入端移动的路径,以及每一次读入端穿过两个字符的边界时的状态(也就相当于每一次移动的起始状态)。对于我们每一次穿过的边界,都对该边界记录下穿过该边界时的状态,那么对于每个边界我们都将得到一个状态序列,被称作crossing sequence\text{crossing sequence}(我也不知道中文是什么)。

需要注意的是,如果2DFA\text{2DFA}接受了输入串,那么产生的所有crossing sequence\text{crossing sequence}中都不会存在移动方向相同的重复状态。容易知道这样必定会在同一个边界处左右横跳产生死循环。

另一个重要的观察结果是,当一个边界第一次被穿过的时候,读入端一定在向右移动。而且后续再次穿过该边界的时候的移动方向一定是与前一次访问时的移动方向相反。因此在一个crossing sequence\text{crossing sequence}中,下标为奇数的元素一定代表着向右移动,而下标为偶数的元素一定代表着向左移动。如果输入串被接受,那么产生的所有crossing sequence\text{crossing sequence}一定长为奇数。由此,如果一个crossing sequence\text{crossing sequence} q1,q2,...,qkq_1,q_2,...,q_k长度为奇数,我们称这个crossing sequence\text{crossing sequence}是有效的。

老师的提示:“每个这种序列本质上是从状态集QQ到状态集QQ的函数f:QQf:Q\to Q,输入是向右移动时的状态,输出是向左回来时的状态,这两个状态就是该序列中相邻的两项。构造的DFA\text{DFA}本质上用这种ff作为状态。”

原书中构造的是NFA\text{NFA},当然也是等价的,用的也是crossing sequence\text{crossing sequence}作为状态。为此,我们首先需要分析相邻的crossing sequence\text{crossing sequence}的性质。

3.左右匹配crossing sequence对\text{3.左右匹配crossing sequence对}

考虑输入字符串上的一个字符aa,设在aa的左边界和右边界处分别给出有效的crossing sequence\text{crossing sequence} q1,q2,...qkq_1,q_2,...q_kp1,p2,...,plp_1,p_2,...,p_l。我们可以用如下方法检测这两个crossing sequence\text{crossing sequence}是否是相容的(一致的),或者说,我们在计算过程中能否在aa的左右边界上分别产生这两个crossing sequence\text{crossing sequence}

如果读入端以状态qiq_iaa字符处向左移动,那么我们以qi+1q_{i+1}为起始状态,从aa处开始,重新启动自动机,这样相当于我们从crossing sequence\text{crossing sequence}中的下一个状态开始继续运行来检测后续序列的相容性。类似的,如果读入端以状态pip_iaa字符处向右移动,那么我们以pi+1p_{i+1}为起始状态,从aa处开始,重新启动自动机,来检测后续序列的相容性。这样的想法给出了下面的两个定义。

定义:我们以如下55个条件递归地给出左匹配和右匹配crossing sequence\text{crossing sequence}对的概念。假设我们初始时以状态q1q_1向右移动到达aa,若q1,q2,...qkq_1,q_2,...q_kp1,p2,...,plp_1,p_2,...,p_l是相容的,称q1,q2,...,qkq_1,q_2,...,q_kaa处右匹配p1,p2,...,plp_1,p_2,...,p_l。假定我们初始时以状态p1p_1向左移动到达aa以状态p1p_1向左移动到达aa,若q1,q2,...qkq_1,q_2,...q_kp1,p2,...,plp_1,p_2,...,p_l是相容的,则称q1,q2,...,qkq_1,q_2,...,q_k于a处左匹配p1,p2,...,plp_1,p_2,...,p_l。这里q1,q2,...qkq_1,q_2,...q_kp1,p2,...,plp_1,p_2,...,p_l分别是我们在aa的左右边界处取的crossing sequence\text{crossing sequence}

注意,因为第一次进入aa时肯定是向右移动,因此理论上说只有右匹配对我们是有意义的,但是为了递归地考虑右匹配我们需要对应地给出左匹配的概念。

接下来给出左右匹配的递归判定条件。

  1. 空序列与空序列左右匹配。也就是说,如果我们根本无法到达aa,那么aa的左右两侧都是空序列。

  2. 如果q3,...,qkq_3,...,q_k右匹配p1,...,plp_1,...,p_l,并且δ(q1,a)=(q2,L)\delta(q_1,a)=(q_2,L),那么q1,...,qkq_1,...,q_k右匹配p1,...,plp_1,...,p_l。亦即,第一次穿过左边界时以状态q1q_1进入状态q2q_2,并且读入端立刻以状态q2q_2左移进入状态q3q_3。如果我们从q3q_3出发得到了一对匹配的crossing sequence\text{crossing sequence},那么说明我们从q1q_1出发得到的一对crossing sequence\text{crossing sequence}也是相容的。

  3. 如果q2,...,qkq_2,...,q_k左匹配p2,...,plp_2,...,p_l并且δ(q1,a)=(p1,R)\delta(q_1,a)=(p_1,R),那么q1,...,qkq_1,...,q_k右匹配p1,...,plp_1,...,p_l。亦即,第一次穿过左边界时以状态q1q_1进入状态p1p_1,并且立即以状态p1p_1右移穿过右边界。

    这里需要注意的是,我们下一次回到aa时,肯定是以p2p_2左移到达aa的,以此为起点考虑接下来的计算过程,这可以看作是原计算过程的一个子过程。在子过程中,我们在左右边界记录下的序列分别是q2,...,qkq_2,...,q_kp2,...,plp_2,...,p_l(开头是q2q_2,是因为q1q_1是我们第一次到达aa时记下的,不在接下来的计算过程中)。因为这个子过程是以q2q_2向左进入aa开始的,因此如果q2,...,qkq_2,...,q_k左匹配p2,...,plp_2,...,p_l我们就能得到q1,...,qkq_1,...,q_k右匹配p1,...,plp_1,...,p_l

  4. 如果q1,...,qkq_1,...,q_k左匹配p3,...,plp_3,...,p_l并且δ(p1,a)=(p2,R)\delta(p_1,a)=(p_2,R),那么q1,...,qkq_1,...,q_k左匹配p1,...,plp_1,...,p_l。这个的解释和第22条类似。

  5. 如果q2,...,qkq_2,...,q_k右匹配p2,...,plp_2,...,p_l并且δ(p1,a)=(q1,L)\delta(p_1,a)=(q_1,L),那么q1,...,qkq_1,...,q_k左匹配p1,...,plp_1,...,p_l。这个的解释和第33条类似。

4.等价性证明\text{4.等价性证明}

定理:如果语言L\text{L}被一个2DFA\text{2DFA}接受,那么L\text{L}是正则语言

Proof:\text{Proof:}

我们设$ M=(Q,\Sigma,\delta,q_0,F)是一个是一个\text{2DFA}$。下面构造一个 NFA M=(Q,Σ,δ,q0,F)\text{NFA }M'=(Q',\Sigma,\delta',q_0',F') 使得 MM'接受L(M)L(M),这里(Q,Σ,δ,q0,F)(Q',\Sigma,\delta',q_0',F')满足如下条件:

  1. QQ'MM产生的所有有效的crossing sequence\text{crossing sequence}组成。

    我们说过,crossing sequence\text{crossing sequence}长度是有限的,因此所有有效的crossing sequence\text{crossing sequence}集合的大小也是有限的。

  2. q0q_0'是仅包含q0q_0crossing sequence\text{crossing sequence}

  3. FF'是所有仅包含FF中的状态的长度为11crossing sequence\text{crossing sequence}组成的集合

    形式化的说,F={[qf]qfF}F'=\{[q_f]|q_f\in F\}

  4. δ(c,a)={dd是于a处右匹配c的有效crossing sequence}\delta'(c,a)=\{d|d\text{是于a处右匹配c的有效crossing sequence}\}

    这里的dd既然是有效的,肯定长度为奇数。注意由于我们构造的是一个NFA\text{NFA},转移函数的像是状态的集合。

因为下面马上会用方括号来表示序列,所以这里FF'的形式化定义我也用了方括号表示序列。

我们的想法是让MM'MM的计算拼在一起。这是通过猜测接下来的crossing sequence\text{crossing sequence}来实现的。如果MM'猜测cc是在某个边界上产生的crossing sequence\text{crossing sequence},并且aa是下一个输入字符,所有于aa处被cc右匹配的crossing sequence\text{crossing sequence}都是可能的下一步,如果我们运气好跑出了输入串的右边界,那MM'就接受了这个字符串。

我们下面来证明L(M)=L(M)L(M')=L(M)。先证L(M)L(M)L(M)\subset L(M')

wL(M)\forall w\in L(M),考虑MMww上的一次接受计算产生的所有crossing sequence\text{crossing sequence}。每个crossing sequence\text{crossing sequence}都右匹配下一个边界处的crossing sequence\text{crossing sequence},所以我们顺着这些crossing sequence\text{crossing sequence}猜就能一路转移到接受状态。

反过来,我们再证明L(M)L(M)L(M')\subset L(M)

wL(M)\forall w\in L(M'),考虑MM'计算w=a1a2...anw=a_1a_2...a_n时产生的crossing sequence\text{crossing sequence}序列c0,c1,...,cnc_0,c_1,...,c_n。那么根据δ\delta'的定义,对于每个i[0,n1]i\in [0,n-1]cic_i右匹配ci+1c_{i+1}ai+1a_{i+1}。我们可以通过决定读入端转向的时机来构造MMww上的合法的计算。具体而言,假设MM'在读取a1a2...aia_1a_2...a_i,我们对ii用归纳法,来证明如下结论。

MM'能进入状态ci=[q1,...,qk]c_i=[q_1,...,q_k],则:

(1)(1) MMq0q_0启动计算a1a2...aia_1a_2...a_i时在ii处会首先以q1q_1状态右移,并且

(2)(2) 对于j=2,4,...j=2,4,...,若MMii处以状态qjq_j启动,MM最终会以状态qj+1q_{j+1}向右移出第ii位。这也说明kk必须为奇数。

原书在此处用[q1,...,qk][q_1,...,q_k]表达crossing sequence\text{crossing sequence}。这里的符号和原书保持一致。

归纳基础(i=0)(i=0)

c0=[q0]c_0=[q_0](1)(1)自动满足,因为MM00处(相当于字符串还没读入)可以看成是“向右移动”读取了a1a_1(2)(2)也显然满足。

归纳证明:

假设结论对i1i-1成立。假定MM'会在读取a1a2...aia_1a_2...a_i后从ci1=[q1,...,qk]c_{i-1}=[q_1,...,q_k]进入状态ci=[p1,...,pl]c_i=[p_1,...,p_l]

因为kkll都是奇数,并且ci1c_{i-1}aia_i处右匹配cic_i,必定存在一个奇数jj使得在状态qjq_j读取aia_iMM向右移动(如果这样的jj全部是偶数,那么只可能是让读写头在aia_i的左边界处反复横跳,那显然是不可能的)。让j1j_1是最小的这样的jj(这样我们先去掉了没有作用的反复横跳的情况)。于是根据右匹配的定义,δ(qj1,a1)=(p1,R)\delta(q_{j_1},a_1)=(p_1,R)

这一结论无需使用前面给出的递归判定条件,但也不是很显然。由于j1j_1是奇数(注意,奇数的条件控制的是在读取aia_i之前读入端右移穿过左边界的行为),从qj1q_{j_1}读取aia_i向右的转移一定是穿过aia_i的左边界到达一个新状态,根据我们对jjj1j_1的约定,读写头这时一定会向右移动穿出aia_i的右边界(注意,这是由jj的约定控制的读入端读取aia_i以后向右移动穿过右边界的行为,这和上面那一次右移的原因不一样),由j1j_1的最小性,以新状态向右移动一定是第一次穿出aia_i的右边界,那么cic_i的第一个元素p1p_1一定是这时产生的。于是我们有δ(qj1,a1)=(p1,R)\delta(q_{j_1},a_1)=(p_1,R)

这就证明了(1)(1)

由前面右匹配定义的第33条,我们有[qj1+1,...,qk][q_{j_1+1},...,q_k]左匹配[p2,...,pl][p_2,...,p_l]

如果对于所有偶数jj都有δ(pj,ai)=(pj+1,R)\delta(p_j,a_i)=(p_{j+1},R)那么(2)(2)显然成立。否则,我们取最小的偶数j2j_2使得δ(pj2,ai)=(qx,L)\delta(p_{j_2},a_i)=(q_{x},L)。目前qxq_{x}不确定,但可以肯定的是,qxq_{x}aia_i左边界的crossing sequence\text{crossing sequence}中的的元素,因为我们在读取aia_i之后立刻向左移动穿出了左边界。

这样,根据前面左匹配的定义的第55条,qxq_{x}一定是qj1+1q_{j_1+1}并且[qj1+2,...,qk][q_{j_1+2},...,q_k]右匹配[pj2+1,...,pl][p_{j_2+1},...,p_l]

这一结论又不是很显然。j2j_2为偶数控制了这一步的移动是穿过aia_i右边界向左移动,到达了新状态qxq_xqxq_x又向左移动穿出了左边界。根据前面对于j1j_1的定义,qj1q_{j_1}的移动是在状态转移至cic_i中的状态之前最后一次穿越左边界(在这之后,读入端马上向右移动穿出右边界了)。由于j2j_2的最小性,这一次移动一定是第一次从cic_i中的状态转移到了ci1c_{i-1}中的状态,并且穿出了左边界。因此,可以知道我们在pj2p_{j_2}转移后,一定是转移到了qj1+1q_{j_1+1}。那么qxq_{x}就是qj1+1q_{j_1+1}。在此基础上直接使用左匹配的定义的第55条就可以得到[qj1+2,...,qk][q_{j_1+2},...,q_k]右匹配[pj2+1,...,pl][p_{j_2+1},...,p_l]

因此我们肯定会从pj2+1p_{j_2+1}穿出右边界移出ii(2)(2)得证。虽然我们也有可能在穿出去之后再左移回来,但是我们只要重复这个过程,不断消去cic_ici1c_{i-1}中的元素,对于MM来说它会在这样的pjp_{j}qjq_{j}之间来回移动直到最终剩下所有偶数jj都有δ(pj,ai)=(pj+1,R)\delta(p_j,a_i)=(p_{j+1},R),这是肯定能达成的,最终否则如果读取了aia_i都是向左移动那么就不会穿出aia_i的右边界,ww也就不会被接受了。这时MM会继续转移到下一个crossing sequence\text{crossing sequence}中的状态。换言之我们不会停在第ii位之前走不出去。

由于cnc_n非空,最后一定能走到cn=[p]c_n=[p],这里pFp\in F。于是MM接受a1a2...ana_1a_2...a_n,有L(M)L(M)L(M)\subset L(M')

于是L(M)=L(M)L(M)=L(M')。定理得证。

5.总结\text{5.总结}

总结个寂寞,累死了。