【字符串】Lyndon 分解
题目描述
定义 Lyndon Word:
给定字符串
最后输出每一个子串右端点异或和。
算法描述
此处使用时间复杂度
首先可以证明 Lyndon 分解存在且唯一。
我们使用
我们断言,
首先我们要知道一件事情:像
也就是说,
-
:容易发现如果将 分出去,就不满足 "前面大于后面" 这个性质,所以 要分在一起。所以从 开始, 整体变成了一个串 ,将指针 。 -
:发现如果将 和前面的串划分成一个,就会出现后缀比整体小的情况,所以确定前面所有 的划分结果,将这些 划分出去,具体方法是将 直到大于 为止。 -
:没有问题,继续匹配下一个 , 。
由此还可以得出每次划分时
由此解答前面的问题,只有在
具体在实现代码的时候,采用枚举
时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int N = 5e6 + 5;
char s[N];
int n;
vector <int> rt;
int main()
{
scanf("%s",s + 1);
n = strlen(s + 1);
int i = 1,j,k;
while(i <= n)
{
for(j = i,k = i + 1;k <= n && s[j] <= s[k];)
{
if(s[j] == s[k]) j++,k++;
else j = i,k++;
}
for(int len = k - j;i <= j;i += (k - j)) rt.push_back(i + len - 1);
}
int res = 0;
for(auto in : rt) res ^= in;
cout<<res;
return 0;
}
用处
目前蒟蒻作者只知道这个可以解决一个串的最小表示法问题:
我们知道每一个 Lyndon 子串小于所有后缀,所以从每个子串的开头一定是最优的,然而我们又知道前面的子串大于等于后面的子串,所以直接取最后一个子串开头即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话