Lyndon 分解小记

来个简单的。

概念#

  • Lyndon 串:一个字符串 s 被称为 Lyndon 串,当且仅当 s 整个串是所有后缀中严格最小的

例如 ababb, abcdefg

  • Lyndon 分解:将字符串 s 分解为 w1,w2,...,wk,满足 w1w2...wk,并且 w1,w2,...,wk 都是 Lyndon 串。

例如 acaababc 可以分解为 ac,aababc

性质#

对于 Lyndon 串 u,v,若 u<v,那么 uv 也是 Lyndon 串

证明
  • u 不是 v 的前缀,那么一定有 uv<v

  • uv 的前缀,由于 v 是 Lyndon 串,那么 v 中以位置 |u|+1 开头的后缀 >v,进而知 uv<v

一个字符串 s 的 Lyndon 分解存在且唯一

存在性证明

w1,w2,...,w|s| 分别为 s1,s2,...,s|s|,这些串都是 Lyndon 串。

对于 i<|s|,如果 wi<wi+1,那么合并 wi,wi+1。由性质①可知,合并后的串仍是 Lyndon 串。

一直合并,最后一定有 w1w2...wk

唯一性证明

使用反证法,若 s 有两种 Lyndon 分解:

  • s=w1w2...wi1wiwi+1...wk

  • s=w1w2...wi1wiwi+1...wj...wk

钦定 |wi||wi|,并且 wi=wiwi+1...wj1pre(wj)

那么 wipre(wj),设 pre(wj)wi 中的开头位置为 p,则 wiwi 中以位置 p 开头的后缀

这与 wi 是 Lyndon 串矛盾。

Duval 算法#

Duval 算法以 O(n)O(1) 的复杂度求出了一个字符串的 Lyndon 分解。

我们维护三个指针 i,j,k,把 s 分成三段,分别为 s1...i1,si...k1,sk...n

同时维护 si...k1 的一个周期 p=kj,即 si...k1=si...i+p1t+pre(si...i+p1),并且 si...i+p1 是 Lyndon 串。

使用增量法,目前考虑加入字符 sk,分三种情况:

  • sj=sk

周期 p 仍然合法,令 jj+1

  • sj<sk

可知 si...k 是一个 Lyndon 串,重新设置周期长度,令 ji

  • sj>sk

本轮分解完毕,得到 Lyndon 串 si...i+p1,si+p...i+2p1,si+2p,i+3p1,...

每轮开始时,令 ji, ki+1

模板题

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define fi first
#define se second
#define pir pair <ll, ll>
#define mkp make_pair
#define pb push_back
using namespace std;
const ll maxn = 5e6 + 10, inf = 1e17;
char s[maxn];
ll n, ans;
int main() {
	scanf("%s", s + 1); n = strlen(s + 1);
	for(ll i = 1; i <= n;) {
		ll j = i, k = i + 1;
		while(k <= n && s[j] <= s[k]) {
			if(s[j] == s[k]) ++j;
			else j = i;
			++k;
		}
		while(i <= j) {
			ans ^= i + k - j - 1;
			i += k - j;
		}
	}
	printf("%lld", ans);
	return 0;
}

这玩意可以直接求解最小表示法,这里懒得写了。

出处:https://www.cnblogs.com/Sktn0089/p/18185129

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Lgx_Q  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示