Lyndon Word and The Runs Theorem

最近回去啃了啃WC的另一份课件,算是为自己两年前的作品写下续章吧。

本文是yjz、xyx、csl三人在WC2019营员交流课件的笔记。

符号和约定

为了方便本文的叙述,采用如下可能不严谨的定义: 我们记w[i:j]表示w从第i个字符到第j个字符组成的子串,当i=1j=|w|时,ij可以省略,i=j时,可以简记为w[i]。 对于字符串u,v,记uv,如果u<vu并非v的前缀,即两者在结束之前就比较出了大小。 一个比较显然的结论是,如果uv,那么对任意字符串w1,w2,有w1uw1vuw1vw2

定义1

如果字符串w满足对于i=2,3,,|w|,都有w<w[i:],那么称w是一个Lyndon串,即w的任意严格后缀都大于w本身。

定理1

如果u,v都是Lyndon串,且u<v,那么uv是Lyndon串。

证明:将uv的后缀(uv)[i:]分为三部分:i[2,|u|],i=|u|+1,i[|u|+2,|uv|]。 对于第一部分,考虑u是一个Lyndon串,对于其严格后缀u[i:],有uu[i:],从而有uv(uv)[i:]。 对于第二部分,若uv,则显然uv(uv)[|u|+1:];否则uv的前缀,有[uv<v][v<v[|u|+1:]],由v是Lyndon串,立得后者成立。 对于第三部分,考虑uv<v<v[i|u|:]=(uv)[i:],i[|u|+2,|uv|]即可。

定理2

如果u是Lyndon串,设a为一个字符,那么对于字符串uku[:i1]a,i[1,|u|],有: 1.若a<u[i],那么u是任意以uku[:i1]a开头的字符串的最长Lyndon前缀。 2.若a>u[i],那么uku[:i1]a是Lyndon串。

证明:对a<u[i]的情况,由于unu[:i]若并非u本身,就是周期串,不可能是Lyndon串。对于剩下的更长的前缀,不妨假设其为uku[:i1]av,从而有u[:i1]av作为后缀,由于u[:i1]au,因此u[:i1]avuku[:i1]av,从而uku[:i1]av不可能是Lyndon串。第一部分得证。 对a>u[i]的情况,将uku[:i1]a的严格后缀分为以u开头的、以u的严格后缀u[i:]开头的和a。对于以u开头的,假设其为uku[:i1]a(k<k),由uu[:i1]a,立得uk+1uku[:i1]a,从而uku[:i1]a<uku[:i1]a;对于以u[i:]开头的,由u[i:]u立得其小于uku[:i1]a;最后,由uu[i]<a,即得a也大于整个串。因此,uku[:i1]a是Lyndon串。

定义2

对于字符串w,若存在一组Lyndon串u1,u2,,un,满足w=u1u2unu1u2un,那么称u1,u2,,unwLyndon分解

定理3

任意字符串w的Lyndon分解存在。

证明:采用构造法并对w的后缀归纳证明。设u1,u2,,umw[2:]的一组Lyndon分解,由于w[1]是Lyndon串,有w=w[1]u1u2um,对于这组“初步的”Lyndon分解,由定理1,只要开头的两个Lyndon串是小于关系,就合并为一个新Lyndon串,反复操作直到只剩下一个串或者是不小于的关系,就得到了w的一组Lyndon分解。

定理4

任意字符串w的Lyndon分解唯一。

证明:只要证明w的任意Lyndon分解的第一个字符串w[:i]一定是w的最长Lyndon前缀,之后考虑余下的串是w[i+1:]的Lyndon分解,归纳证明即可。 反证法,假设存在更长的Lyndon前缀w[:j](i<j),则该Lyndon分解w[:i]u2u3un中,存在一个uk满足其是第一个右端点位置j的串,不妨记为w[i:j],考虑w[:j]是Lyndon串,因此w[:i]<w[:j]<w[i:j]w[i:j]=uk,得到w[:i]<uk,与Lyndon分解是不递增的矛盾。综上所述Lyndon分解唯一。

初步的Lyndon分解算法

在定理4保证了Lyndon分解的唯一性后,定理3实际上给出了一个求Lyndon分解的算法。通过哈希或后缀数组预处理后判断子串的大小关系,并沿用定理3证明中的过程,就可以做到O(nlogn)求解Lyndon分解。当然,采用SA-ISO(n)O(1)RMQ可以使算法做到O(n),然而这样的实现并不实用。

高效的Lyndon分解算法

通过定理2给我们的启发,有可能找到更好的Lyndon分解算法。考虑将w划分为三部分,记录i,k,p表示w[:i]已经进行了Lyndon分解,并确定必定是w的Lyndon分解的前若干项,而w[i+1:k]则是一个形如uku[:j1]的串,其中u是Lyndon串且长度为pw[k+1:]则是未知情况的串。 考虑不断进行如下迭代,直到i变为|w|: 考察w[k+1](若k+1>|w|,则定义w[k+1]是小于任何字符集中字符的特殊字符$),分三类情况: 1.w[k+1]=w[k+1p],则uku[:j1]的形式继续保持,令k自增1即可。 2.w[k+1]>w[k+1p],则由定理2可知,w[i+1,k+1]是一个Lyndon串,但是不能保证其一定出现在最终的Lyndon分解中。不过,这仍满足uku[:j1]的形式(k=j=1),于是令k自增1,而pki+1即可。 3.w[k+1]<w[k+1p],则由定理2可知,u必定是w[i+1:]的最长Lyndon前缀。由定理4可知,其一定出现在Lyndon分解中,于是我们将ku全部加入已知的Lyndon分解中。对于剩下的u[:j1],无法保证其满足uku[:j1]的形式,干脆重新开始,令k指向u[:j1]的第一个字符(单字符必定是Lyndon串),并令i=k1,p=1

综上即得Lyndon分解,每次迭代是O(1)的,且i+k至少增加1。由于i,k|w|,因此整个算法是O(n)的,并且有非常简洁的实现。

The Runs Theorem 部分待填坑。