“每次成功合并减少一个块,因此总合并次数至多 $n 1$。但这不能推出字符时间线性:比较两块可能扫描长公共前缀,连接也可能复制全部字符。上面朴素实现有 $O(n)$ 次块操作、每次最坏 $O(…”
CFL 定理已经告诉我们,bbaabbaabbaa 必须分成 b|b|aabb|aabb|a|a。但若不断创建字符串切片、比较整块、再把块合并,即使合并次数不多,也可能反复扫描同一批字符。
Duval 算法只移动三个索引。它暂时把已扫描部分理解为“某个 Lyndon 块重复若干次,再跟着该块的一小段前缀”。一个新字符到来时,算法只需判断它是等于、大于还是小于原来期待的字符。三种结果分别表示继续重复、形成更大的 Lyndon 块、或结束当前批次。
形式陈述
三个索引在看什么
采用零下标和半开区间,输入为长度
是尚未输出部分的起点 是下一个待查看的位置,初始为 是用来与 比较的位置,初始为
在扫描尚未停止时,令
换言之,当前扫描段按长度
初始段只有一个字符,
直觉
相等、变大、变小,分别发生什么
若
若
若
关键是第二种情形为何合法。把旧段写成
这条扩张规则不是普通周期串都具备的性质。它依赖基本块
一次输出多少个块
扫描停止时,
代码不必显式计算
def duval_intervals(s):
n = len(s)
i = 0
while i < n:
j, k = i + 1, i
while j < n and s[k] <= s[j]:
if s[k] < s[j]:
k = i
else:
k += 1
j += 1
p = j - k
while i <= k:
yield (i, i + p)
i += p
输出的是区间,调用者需要字符时再访问输入。空串不进入外循环,自然输出空序列。相等字符必须走 k += 1 分支;若每次都把 aaaa 错当成越来越长的块,而它的正确分解是四个单字符。
为什么输出不会被未来推翻
停止时扫描段为
根据 CFL 存在性,剩余串拥有一份合法分解。它的第一个因子是剩余串的前缀,因此不大于剩余串,进而小于
唯一性定理随即保证,这批
例子与边界
完整手算十二个字符
输入位置与字符为:
| 位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 字符 | b | b | a | a | b | b | a | a | b | b | a | a |
第一轮 b,相等分支把 a<b,扫描停止。b。
第二轮从
| 比较 | 动作 | ||
|---|---|---|---|
| 3 | 2 | a = a | 保持周期一,继续 |
| 4 | 3 | a < b | 令 k=2,基本块扩成 aab |
| 5 | 2 | a < b | 令 k=2,基本块扩成 aabb |
| 6 | 2 | a = a | 继续第二份 |
| 7 | 3 | a = a | 继续第二份 |
| 8 | 4 | b = b | 继续第二份 |
| 9 | 5 | b = b | 第二份读完 |
| 10 | 6 | a = a | 进入短前缀 aa |
| 11 | 7 | a = a | 到达串尾 |
停止时 aabbaabbaa 是 aa 塞进四字符因子。
第三轮 a 给出周期一,输出
迁移练习与反例
对 abbabbaba,第一轮在位置八的 a 处遇到下降,已扫描 abbabbab。它是 abb,剩余 aba 再分成 ab|a。最终为 abb|abb|ab|a。
这个实例与串尾停止不同:下降字符本身还没被消费,下轮必须把它保留下来。如果把下一轮起点设成
算法擅长顺序分解,却不意味着输入每到一个字符就能立刻永久输出所有前面因子。例如 aaa 暂时分成三个 a,再接 b 后整串 aaab 成为一个 Lyndon 词。完整字符串的线性扫描,与必须立即承诺输出的在线接口,是两种不同要求。
推论与应用
线性时间要给重新扫描的部分记账
“
固定一轮起点
由于
代码中相等或变大的一步可能调用两次关系比较,停止时可能再调用一次;同样的批次账本给出少于
生成器只保存常数个下标,辅助工作空间为
参考资料
- [1] Jean-Pierre Duval, “Factorizing Words over an Ordered Alphabet”, Journal of Algorithms 4(4), 1983, pp. 363–381。
- [2] Sukhpal Singh Ghuman, Emanuele Giaquinta and Jorma Tarhio, “Alternative Algorithms for Lyndon Factorization”, 2014,§3、Figure 1、Lemmas 2–4:Duval 的重复前缀结构与三种扩张情形。本文换成统一的零下标半开区间,并独立给出批次计费和十二字符实例。
- M. Lothaire, Applied Combinatorics on Words, Cambridge University Press, 2005:词分解与字符串算法背景。