Lyndon 词与 Lyndon 分解
基本约定与前置知识
- 非空集合
A 称为字母表,A^* 为由A 中字母构成的所有有限长的词的集合,记\emptyset 为空词,A^+ = A^* \backslash \{\emptyset\} 为其中非空串的集合。类似地,对w \in A^* 有记法w^* 表示有限多个w 拼接构成的词的集合。 - 称
w \in A^+ 本原,若:
- 称
x, y \in A^* 共轭,若:
- 命题 1.3.4
更确切地说,$\exists u, v \in A^*, \text{s.t. } x = uv, y = vu$,此处的 $z$ 满足 $z \in u(vu)^*$。
5.1 Lyndon 词与 Lyndon 分解
定义 5.1.1 (字典序)
给定全序
设
x, y \in A^* 。\ (1) 当x = \emptyset ,令x \leq y 恒成立。\ (2) 当x \neq \emptyset, y = \emptyset ,令x \leq y 恒不成立。\ (3) 当x, y \neq \emptyset ,设x = ax', y = by' ,其中a, b \in A, x', y' \in A^* ,令x \leq y 当且仅当a < b \lor (a = b \land x' \leq y') 。
称
命题 5.1.2 (字典序的基本性质)
(1)
\forall u, v, w \in A^*, u < v \Leftrightarrow wu < wv 。\ (2)\forall u, v, w, x \in A^*, v \not\in uA^* \Rightarrow (u < v \Leftrightarrow uw < vx) 。
Proof. 归纳即得。
定义 5.1.3 (Lyndon 词)
称
记所有 Lyndon 词构成集合
当
例子 5.1.4
设
命题 5.1.5
设
w \in A^+ ,则w 为 Lyndon 词当且仅当w 小于其所有真后缀。或者形式化地说:
Proof. 先证充分性。由条件立即得到:
明所欲证。
再证必要性。首先说明
进而有
这与最小性矛盾,故证得
由
推论 5.1.6
若
w \in A^+ 为 Lyndon 词,则其没有 border。
Proof. 考虑反证法:设
命题 5.1.7
Proof. 先证充分性,只需讨论
- (i) 若
m \in lA^* ,设m = lm' ,则m \in L 与 命题 5.1.5 指出m < m' ,故w = lm < lm' = m 。 - (ii) 若
m \not\in lA^* ,由l < m 可知w = lm < m 。
接下来分类讨论
- (i) 若
v 为m 的真后缀,命题 5.1.5 指出w < m < v 。 - (ii) 若
v = v' m ,其中v' 为l 的真后缀,命题 5.1.5 指出l < v' ,进而有w = lm < v' m = v 。
总之
再证必要性,同样只需讨论
设
设
若
故由
进而根据 命题 5.1.5 可知
最终,
- (i) 若
m \in lA^* ,则l \leq m 。若l = m 则w = l^2 ,与其本原性矛盾,故l < m 。 - (ii) 若
m \not\in lA^* ,由w = lm < m 可知l < m 。
总之,我们给出了分解
上述命题的必要性证明也给出了一个递归构造 Lyndon 词的方法;同时,对于每个
定义 5.1.8 (标准分解)
设
Remark. Lyndon 词按照 命题 5.1.7 的叙述分解时所得结果未必唯一,例如
定理 5.1.9 (Lyndon 分解定理)
设
w \in A^+ ,则其可唯一表作递降的 Lyndon 词之积。或者形式化地说:
Proof. 先证存在性。首先由于
断言这种分解满足
再证唯一性。设
- (i) 当
n = 0 ,命题显然正确。 - (ii) 当
n > 0 ,显然n' > 0 ,若l_1 \neq l'_1 ,不妨设l'_1 为l_1 的前缀,令l_1 = l'_1 \cdots l'_i u ,其中1 \leq i < n' ,u \neq \emptyset 为l'_{i + 1} 的前缀。 - 由 命题 5.1.5 可知
l_1 < u ,由前缀的性质可知u \leq l'_{i + 1}, l_1' < l_1 。 - 再由不等式链,综合得到
l_1 < u \leq l'_{i + 1} \leq l'_1 < l_1 ,矛盾! - 故有
l_1 = l_1' ,由归纳假设即证。
为了求解 Lyndon 分解,一个自然的想法是“剥洋葱”——即逐步析出分解中的首项或末项。下面阐述了有关这两项的一些性质。
命题 5.1.10
设
w \in A^+ 的 Lyndon 分解为w = l_1 \cdots l_n ,则:\ (1)l_n 为w 的最小非空后缀。\ (2)l_n 为w 的最长 Lyndon 后缀。\ (3)l_1 为w 的最长 Lyndon 前缀。
Proof. (1) 设
若
若
故有
(2) 设
若
故
(3) 设
若
由
故
上面命题 (1) 给出了一种直截了当但效率不高——每次拆出一个最小非空后缀;接下来讨论另一种思路——增量式维护前缀,这正是大名鼎鼎的 Duval 算法。
让我们来刻画 Lyndon 词的前缀。记
显见
推论 5.1.11
设
u, v \in L, u < v ,则\forall k, k' \in \mathbb{N}_+, u^k v^{k'} \in L 。
Proof. 由 命题 5.1.7 立即可得。
命题 5.1.12
设
u \in A^*, v \in A^+, uv \in L ,若a \in A, v < a ,则ua \in L 。
Proof.
设
由
故
引理 5.1.13
设
w = (uav')^k u ,其中u, v' \in A^*, a \in A, k \in \mathbb{N}_+, uav' \in L ,则:\ (1)\forall a' \in A, a' > a \Leftrightarrow wa' \in L 。
Proof. (1) 先证必要性。假设
再证充分性。由
- 那么压力给到了
a' \leq a 的情况,我们需要讨论何时能够将其保留为某个 Lyndon 串的前缀。 - 当
a' = a ,若uav' 中不止含A 的最大元(如果存在的话),只需在非最大元下一次周期出现的地方插入最大元,就能使之成为一个 Lyndon 串。 - 否则,
uav' 必须恰好为最大元这一个单字符。方便起见,我们对P 的定义稍加扩展。
下面先对
在此基础上阐述
(2)
wa \in P' \backslash L 。\ (3)\forall a' \in A, a' < a \Rightarrow wa' \not\in P' 。
Proof. (2) 当
当
(3) 对任意
上面引理的结论提示我们,
命题 5.1.14 (前缀候选集 \Leftrightarrow 严格半幂集)
Proof.
下证
- 设
w = w' a' \in P' \backslash L ,则w' \in P', |w'| = |w| - 1 。 - 由归纳假设,
w' 可以表示为(uav')^k u ,其中u, v' \in A^*, a \in A 。 - (i) 若
a' > a ,由 引理 5.1.13 (1) 可知w \in L ,矛盾! - (ii) 若
a' = a ,有w = (uav')^k (ua) \in S 。 - (iii) 若
a' < a ,由 引理 5.1.13 (3) 可知w \not\in P' ,矛盾!
综上,明所欲证。
命题 5.1.15 (前缀增量时标准分解式的变化)
设
u, v' \in A^*, a \in A, k \in \mathbb{N}_+, uav' \in L ,记\text{CFL}(x) 为x \in A^* 的标准分解式。\ (1)
(2) 设
w = (uav')^k ua' h ,其中a' \in A, h \in A^*, a' < a ,则:
Proof. (1) 设
- (i) 若
s = \emptyset ,则由本原性可知i = 1 ,此即uav' \in L ,满足条件。 - (ii) 若
s \neq \emptyset ,则可见s 为(uav')^i s 的 border,由 推论 5.1.6 推知矛盾。
综上,在
(2) 由 引理 5.1.13 (3) 可知
算法 5.1.16 (Duval 算法)
输入:词
w \in A^+ 。\ 输出:分解式序列[l_1, \cdots, l_n] \in L^n ,满足w = l_1 \cdots l_n, l_1 \geq \cdots \geq l_n 。\ 状态类别:三元组([l_1, \cdots, l_n], \text{null}, w) 或([l_1, \cdots, l_n], (u, av', k), w) 。\ 初始状态:([], \text{null}, w) 。\ 转移 I / 析出:([l_1, \cdots, l_n], \text{null}, aw') \Rightarrow ([l_1, \cdots, l_n], (\emptyset, a, 1), w') \ 转移 II / 大字移进:当a' > a ,([l_1, \cdots, l_n], (u, av', k), a' w') \Rightarrow ([l_1, \cdots, l_n], (\emptyset, (uav')^k ua', 1), w') \ 转移 III / 同字移进:([l_1, \cdots, l_n], (u, av', k), aw') \Rightarrow ([l_1, \cdots, l_n], (ua, v', k), w') \ 转移 IV / 周期更新:([l_1, \cdots, l_n], (u, \emptyset, k), w) \Rightarrow ([l_1, \cdots, l_n], (\emptyset, u, k + 1), w) \ 转移 V / 词尾:([l_1, \cdots, l_n], (u, av', k), \emptyset) \Rightarrow ([l_1, \cdots, l_n] + [uav']^k, \text{null}, u) \ 转移 VI / 小字移进:当a' < a ,([l_1, \cdots, l_n], (u, av', k), a' w') \Rightarrow ([l_1, \cdots, l_n] + [uav']^k, \text{null}, ua' w') \ 终止状态:([l_1, \cdots, l_n], \text{null}, \emptyset) ,此时输出[l_1, \cdots, l_n] 。
正确性证明: 算法维护的不变式为,当状态为
- 转移 I:单字母
a \in A \subset L ,初始化为周期(\emptyset, a, 1) ,即(uav')^1 u = a \in L 。不变式成立。 - 转移 II:由 引理 5.1.13 (1) 可知
(uav')^k ua' \in L ,故整个已累积前缀构成一个 Lyndon 词,算法将其封装为新一轮的周期。不变式保持。 - 转移 III:将
a 并入u 以延长当前周期内的前缀匹配,未匹配的后缀部分缩短一个字符,周期数k 不变。不变式保持。 - 转移 IV:当前周期恰好被完整匹配一遍,周期数
k 加一。不变式保持。 - 转移 V:由 命题 5.1.15 (1) 可知剩余部分的标准分解式包含
k 个完整周期uav' ,剩余u 重新初始化。不变式保持。 - 转移 VI(
a' < a ):由 命题 5.1.15 (2) 可知剩余部分的标准分解式包含k 个完整周期uav' ,剩余ua' w' 重新初始化。不变式保持。
每次析出后,输出序列仍单调不增:因为新析出的
时间复杂度: 将比较分为两类:
- 大字或同字(
a' \geq a ,转移 II / III):扫描指针前进一位,而每个字母至多被从w 中去除而消耗一次,故合计\leq |w| 次比较。 - 词尾(转移 V)或小字(
a' < a ,转移 VI):此时将有至少一个字母被移入已输出的部分,而每个字母只会恰好被移入一次,故合计\leq |w| 次比较。
综上,总比较次数
实现中,可以用指针
实现(Luogu P6114 【模板】Lyndon 分解):
#include <stdio.h>
#include <string.h>
int pos[5000001];
char s[5000001];
int lyndon_decomposite(char s[], int ans[]){
int n = strlen(s), m = 0;
int i = 0;
while (i < n){
int j = i, k = i + 1;
while (k < n && s[k] >= s[j]){
if (s[k] > s[j]){
j = i;
} else {
j++;
}
k++;
}
int d = k - j;
while (i <= j){
i += d;
ans[m++] = i;
}
}
return m;
}
int main(){
scanf("%s", s);
int m = lyndon_decomposite(s, pos), ans = 0;
for (int i = 0; i < m; i++){
ans ^= pos[i];
}
printf("%d", ans);
return 0;
}
Reference
- M. Lothaire, Combinatorics on Words, Addison-Wesley, Reading, Massachusetts, 1982.
- J.-P. Duval, Factorizing words over an ordered alphabet, Journal of Algorithms, Vol. 4, No. 4, pp. 363–381, 1983.