学习笔记(Lyndon 分解)

Lyndon 串:

对于字符串 s ,如果 s 的字典序严格小于 s 的所有后缀的字典序,我们称 是简单串,或者 Lyndon 串 。举一些例子 a , ab , aab , abb , ababb , abcd 都是 Lyndon 串。
如果 s 是 Lyndon 串,当且仅当 s 的字典序严格小于它的所有非平凡的循环同构串。

Lyndon 分解:

串 s 的 Lyndon 分解记为 s=s1s2s3 …sk ,其中所有 为简单串,并且他们的字典序按照非严格单减排序,即 s1>=s2>=s3 。可以发现,这样的分解存在且唯一。

Duval算法

进行lyndon分解,可以使用Duval算法进行处理,这里简述一下这个算法过程,具体的过程可以参考 IO Wiki Lyndon分解
Duval算法采用贪心的思想,将一个字符串分成三个部分,即:已分解s1,正在处理s2,未处理s3,将字符一个一个处理。因此整个字符串S=s1s2s3
使用三个下标i j k标记字符串,其中i表示s2的起始位置,j表示s3的起始位置即新加入的字符,k代表着j位字符在s2上一个循环节对应的字符。
每一次,若
s[j] == s[k],意味着j对应着s2某个循环节的一个字符,拼在s2的末尾使得其仍满足其近似简单性,使j k同时向后移动一步。例如s2=aab,s[j] = a,s[k] = a
s[j] > s[k],意味着循环节失效,新的字符直接拼到s2的末尾,使得新的s2整体就是一个lyndon串,例如:abab —> ababc,此时让k = i,j++
s[j] < s[k],此时s[j]拼在s2的末尾就会影响其简单性了,那么就不能继续添加,转而应该将s2中现有的lyndon串全部分解出来变成s1的一部分,其中的lyndon串就是完整的循环节剩下的继续上面的过程。例如,abbabbab + a --> abb|abb| ab + a前面两个abb就是已经可以确认的lyndon串。但是后面剩下的ab就不是lyndon串了。不难发现,完整的lyndon串的起始位置都小于等于k且长度为j - k。
原文链接

你可能感兴趣的:(知识点,#字符串,c++,算法)