Lyndon 分解
Lyndon 分解
以下所有字符串的大小关系都是对字符串字典序的比较。
定义串 为 Lyndon 串当且仅当 小于其所有不为 的后缀。
该命题等架于 是它的所有循环表示中最小的。
定义串 的 Lyndon 分解为将 分为若干部分 使得 为 Lyndon 串且 。
可以证明任何串 的 Lyndon 分解存在且唯一。
证明这一点需要一个引理:
引理 1:若串 为 Lydnon 串且 ,则 也为 Lyndon 串。
证明:
若 :则 ,那么 的后缀依然 ,得证。
若 :若 不为 的前缀则 得证。否则,设 ,有 ,与 是 Lyndon 串矛盾
Lyndon 分解的存在性证明:
根据引理,不难得到一个 Lydnon 分解的构造方案:
初始令 ,显然这满足 为 Lyndon 串的条件。接下来不断找到 的位置,将 合并到一起,得到的串依然是 Lyndon 串。
Lyndon 分解的唯一性证明:
设 存在两个 Lyndon 分解:
。
找到最小的 使得 ,不妨设 ,设 ,则有 ,矛盾。
在讨论 Lyndon 分解的 构造前,再给出引理:
引理 2:若字符串 与字符 ,满足 是 Lyndon 串的前缀,则对于字符 有 是 Lyndon 串。
证明:
设 为 Lyndon 串。则 ,,故 ,,同时又有 ,故得证。
Duval 算法:
算法的每一时刻都将串 分为三个部分 ,其中 是已经确定的分解, 是未分解的部分, 是正在分解的部分,且 ,其中 是 的一个前缀, 是一个 Lyndon 串。
每一步将 的第一个字母 加入 中,记 :
-
当 时:直接将 加入 中,性质不发生变化。
-
当 时:直接将 的分解方式确定下来,从 的开头重新进行上述流程。
-
当 时, 会得到新的 Lyndon 串,根据之前的 Lyndon 分解的构造方法,这个 Lyndon 串会不断向前合并,最终 得到新的 Lyndon 串,成为新的 。
据此就得到了 求解 Lyndon 分解的方法。
洛谷模板题 P6114 代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
char s[N];
int n,ans;
int main(){
scanf("%s",s+1);
n=strlen(s+1);
int i=1,j,k;
while(i<=n){
j=i,k=i+1;
for(;k<=n&&s[k]>=s[j];++k)
j=s[k]>s[j]?i:j+1;
while(i<=j) ans^=i+k-j-1,i+=k-j;
}
printf("%d\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2021-06-11 "Orz Panda" Cup F.Flow of Orz Pandas