Lyndon Word 小记

rlc202204 / 2024-08-04 / 原文

1. 定义

一个字符串 \(S\) 被定义为 Lyndon Word 当且仅当其严格小于所有真 cyclic shift。

Lyndon Word 的等价定义:是其所有后缀中最小的。

2. 性质

性质 1: Lyndon Word 无 \(\text{Border}\)

不妨设 \(w\)\(\text{Border}\),则我们可以表示为 \(w = xu = uy\),从而得到 \(w < ux, w < uy\),替换一下得到 \(y < x\)\(x < y\),显然矛盾。

性质 2: \(u, v\) 都是 Lyndon Word,则 \(uv\) 是 Lyndon Word \(\iff u < v\)

如果 \(uv\) 是 Lyndon Word,则我们得到 \(uv < v\),同时 \(u < uv\),所以 \(u < v\)

我们分情况考虑三种后缀。

第一种,\(s = u'v\)我们知道 \(u < u'\),因为 \(|u| > |u'|\),所以加上 \(v\) 依然成立。

第二种 \(v\),我们考虑证明 \(uv < v\),按照长度来,如果 \(u > v\) 显然成立,否则若 \(u\)\(v\) 的前缀,不妨设 \(v = uv'\),我们已知 \(v < v'\),所以 \(uv < uv'\) 得证。

第三种比 \(v\) 还小的可以从第二种直接看出来。

性质 3: \(w\) 是 Lyndon Word \(\iff \forall w = uv\)\(u < v\)\(u, v\) 非空)

从左边往右,我们知道 \(uv < v\)\(u < uv\) 即可推出。

反过来,我们需要证明 \(uv < vu\),这是根据定义来证明,分两种情况。

我们设 \(a<_!b\) 表示 \(a\) 小于 \(b\) 且不是 \(b\) 的前缀。

如果 \(u<_!v\),则不难推出 \(uv < vu\)。否则,我们设 \(v = u^kr\),其中 \(u\) 不是 \(r\) 的前缀。

由于 \(w = uv = u^{k+1}r\),得到 \(u^{k+1} < r\) 从而 \(u < r\),于是 \(u <_! r\) 最终得到 \(ur < ru\)

所以我们有 \(uv = u^{k} u r > u^{k}ru = vu\),得证。

性质 4(标准分解): \(w\) 是 Lyndon Word,取最小真后缀 \(v\),假设 \(w = uv\),则:\(u,v\) 也是 Lyndon Word 且 \(u < v\),并且 \(v\)\(w\) 的最长 Lyndon Word 真后缀。

由于 \(v\) 是最小真后缀,所以显然 \(v\) 是 Lyndon Word,而 \(u\) 的所有后缀 \(u'\) 均满足 \(uv < u'v\),由于 \(|u| > |u'|\),说明 \(u\) 一定小于 \(u'\)

递归定义: \(w\) 是 Lyndon Word 当且仅当 \(|w| = 1\) 或存在 \(w = uv, u < v\)\(u, v\) 是 Lyndon Word。

递归定义是性质 4 的推论。

3. Lyndon 分解

重头戏来了。

将任意字符串 \(s\) 分解为若干 Lyndon Word \(t_1t_2\dots t_m\),满足 \(t_1 \ge t_2 \ge t_3 \ge \dots \ge t_m\),称作 Lyndon 分解。

性质 5: Lyndon 分解存在且唯一。

其实很简单,我们考虑先都分成单个字符,然后只要有 \(s_i < s_{i+1}\) 我们就合并,根据性质 2 得到的依然是 Lyndon Word,所以肯定存在。

再考虑唯一性,我们反证法,假设不唯一,存在一个 \(t_i = t'_it'_{i+1}\dots t'_{k}pre(t'_{k+1})\),我们能够推出 \(t_i < pre(t'_{k+1})\le t'_{k+1} \le t'_{i}\),但是前缀关系使得 \(t'_i < t_i\),矛盾!所以得证。

我们一般将 \(s\) 的 Lyndon 分解称作 \(\text{CFL(s)}\)

性质 6: \(\text{CFL(w)} = w_1w_2\dots w_m\),那么:

  1. \(w_m\)\(w\) 的最小后缀。

  2. \(w_m\) 是最长的 Lyndon Word 后缀。

  3. \(w_1\) 是最长的 Lyndon Word 前缀。

证明:

  1. 我们考虑任何一个后缀 \(s = suf(w_i)w_{i+1}\dots w_{m}\),能得到 \(s \ge suf(w_i) \ge w_{i + 1} \ge \dots w_m\),所以 \(\forall s, w_m \le s\)

  2. 上面的证明中设 \(s\) 严格长于 \(w_m\),则 \(i < m\), \(suf(w_i) < s, w_m < s\),从而推出 \(s\) 不是 Lyndon Word。

  3. \(T = w_1w_2\dots w_ipre(w_{i+1})\),则 \(pre(w_{i+1}) \le w_{i+1} \le w_{i} \le \dots \le w_1 \le T\),所以 \(pre(w_{i+1}) \le T\),不是 Lyndon Word。

性质7:\(\text{CFL(w)} = w_1w_2\dots w_m\) 其中 \(w_i\) 的位置是 \([l_i, r_i]\),则所有 \([1,r_i]\) 开始的后缀中,\(l_i\) 开始的是最小的。

对于 \(x > l_i\),很容易证明 \(suf(x) > suf(l_i)\)

否则,我们设 \(suf(x) = w'_{j}w_{j+1}\dots w_m\),所以 \(w_i \le w_j \le w'_j\)

如果 \(w_i <_!w'_j\),则可以证明 \(suf(x) > suf(l_i)\),否则 \(w_i\)\(w'_j\) 前缀,我们可以归纳证明,已经证明了 \(w_{i + 1} < w'_{j+1}\),然后就能证明 \(suf(x) > suf(l_i)\) 了。

4. Duval 算法

这个算法可以用来求 Lyndon 分解。

我们称 \(t = w^kw'\) 为准 Lyndon Word 当且仅当 \(w'\)\(w\) 的前缀并且 \(w\) 是 Lyndon Word。

性质 8: \(c < c'\)(字符),\(vc\) 是某个 Lyndon Word 的前缀 \(\to\) \(vc'\) 是 Lyndon Word。

假设 \(vcu\) 是 Lyndon Word,那么 \(v\) 的任何一个后缀加上 \(c'\) 肯定要大于 \(vc'\),所以得证了。

我们开始描述这个算法流程。这是一个增量算法。

不妨假设现在我们已经固定了 \(s_1 \dots s_y\),后面是若干个 \(t\) 和一个 \(t'\) 满足 \(t'\)\(t\) 的前缀。

现在 \(i\) 等于第一个 \(t\) 开始的位置,\(j,k\) 是当前的比较,满足 \(j = k + |t| - 1\)

然后是过程:

  1. 如果 \(w_k = w_j\),则 \(k,j\) 都增大 1。

  2. 如果 \(w_k > w_j\),则合并所有的 \(t\)\(t'\)\(w_k\),根据引理,这个串是 Lyndon Word,所以成为新的 \(t\)

  3. 如果 \(w_k < w_j\),我们将所有的 \(t\) 固定下来,然后将算法回到 \(t'\) 开始的位置重新开始。

考虑到每次 \(k\) 往回退 \(i\) 至少往前移相同距离,所以时间复杂度是 \(O(n)\) 的。

P6114 【模板】Lyndon 分解

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
string s;
int n;
int main() {
	cin >> s;
	n = (int)s.size();
	s = "=" + s;
	int i = 1, j = 0, k = 0;
	int ans = 0;
	while (i <= n) {
		j = i;
		k = i + 1;
		while (k <= n && s[k] >= s[j]) {
			if (s[j] < s[k])
				j = i;
			else
				j++;
			k++;
		}
		while (i <= j) {
			ans ^= (i + (k - j) - 1);
			i += (k - j); 
		}
	}	
	cout << ans << endl;
	return 0;
}

5. 应用

P1368 【模板】最小表示法

根据性质 7 我们不难得出结论:将原串复制两遍求 Lyndon 分解,然后我们取 \(n\) 所在的串开头作为最小表示即可。

提交记录

debruijn sequence

这个序列指的是一个长度为 \(2^n\) 的 01 串,放在一个圆上,使得任意位置开头的子串可以包含所有的 \(n\) 长二进制串。

我们有结论:将所有 \(n\) 的因子长度的 Lyndon Word 按照字典序从小到大拼接起来得到的就是这个序列。

这个结论对任意字符集都成立。

Lyndon Word 的生成

我们考虑如何生成所有长度小于等于 \(n\) 的 Lyndon Word,这个生成算法是线性的。

我们先生成字典序最小的,然后将上一个复制若干遍填满 \(n\),然后对最后一个位置加 1,如果超过了就进位并删除这一位。这样生成的就是按照字典序拍好的所有 Lyndon Word。

比如长度为 4 的:

0

0001

001

0011

01

011

0111

1

共 8 个。

Lyndon Word 计数

假设字符集大小是 \(k\),那么我们考虑有多少长度为 \(n\) 的 Lyndon Word。

考虑到每个 Lyndon Word 都是一个串的最小表示且没有循环节,我们相当于计数所有的无循环节的项链。

我们先考虑允许循环节的。我们将所有的答案位移 \(n\) 次组成一个表格。

于是我们考虑计数每个串的出现次数,然后除以 \(n\) 即可。对于一个循环节为 \(i\) 的串,其在表格中的循环节为 \(\gcd(n,i)\),所以答案是:

\[\frac{1}{n}\sum_{i=1}^nk^{\gcd(n, i)} \]

然后大力推式子得到:

\[\frac{1}{n}\sum_{d|n}\varphi(d)k^{\frac{n}{d}} \]

然后用莫比乌斯反演得到没有循环节的答案是:

\[\frac{1}{n}\sum_{d|n}\mu(d)k^{\frac{n}{d}} \]