热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

探索Lyndon串的奥秘

在夜晚的宁静中,我们共同探讨一个复杂的算法问题——寻找特定条件下的Lyndon串。本文将深入解析这一挑战,并分享解决问题的独特思路。

引言

每当夜幕降临,我们仰望星空,心中总有许多未解之谜。今天,我们将探讨一个编程领域的难题——如何找到特定条件下的Lyndon串。这不仅是一场技术的较量,更是一次思维的碰撞。

Lyndon串简介

Lyndon串是一种特殊的字符串,其定义为:一个字符串是Lyndon串当且仅当它是该字符串的所有循环移位中字典序最小的。此外,Lyndon串不能是任何非平凡的循环串(即不能通过自身的一部分重复得到)。

问题描述

给定正整数n和字符串p,以及正整数k,我们需要找到长度不超过n且字典序大于等于p的所有Lyndon串中,字典序第k小的那个串。这个问题看似简单,实则充满挑战,尤其是当贪心策略失效时,更需要我们深入思考。

解决方案

解决这一问题的核心在于动态规划与深度优先搜索的结合。首先,我们需要计算以p开头的Lyndon串的数量x。根据x与k的关系,我们可以逐步缩小搜索范围:

  • 如果x >= k,说明p是答案的前缀,但不一定就是答案。此时,我们可以将k减1,并在p后添加一个'a'继续搜索。
  • 如果x

为了确保每个合法串都被恰好计算一次,我们引入了循环节的概念。对于一个合法串,若p在其内部出现了c次,则该串有c种不同的循环表示方式,每种表示方式都应为答案贡献1/c的权重。

动态规划的具体实现

我们使用一个三维数组dp[i][j][c]来表示从当前位置开始,尝试匹配p的第j个字符,已匹配c次p的方案数。通过递推公式,我们可以逐步构建出最终的解。

在具体实现中,我们还需要处理一些特殊情况,如字符串的边界条件和循环节的计算。这些细节的处理对于算法的正确性和效率至关重要。

代码实现

点击查看代码
#include 
using namespace std;
typedef long long ll;
const int maxn = 53;
const int mod = 998244353;
const ll inf = 4e18;
int n, m, nxt[maxn];
ll f[maxn][maxn][maxn], g[maxn], K;
char s[maxn];
#define gcd __gcd
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch <'0' || ch > '9')
{
if(ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x <<1) + (x <<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline bool inc() {for( ; m&&s[m]=='z'; s[m--]=0); return m?s[m]++,1:0;}
inline void add(ll &x, ll y) {x = min(inf, x+y);}
inline ll mul(ll x, ll y) {return 1.0*x*y>2*inf?inf:min(inf, x*y);}
inline bool chk()
{
for(int i=2; i<=m; i++)
{
if(strcmp(s+1, s+i)>0) return 0;
}
return 1;
}
inline bool chk2(int j=1)
{
for(int i=2; i<=m; i++)
{
if(s[i] if(s[i] == s[j]) j++;
else j = 1;
}
return 1;
}
ll calc()
{
if(!chk2()) return 0;
for(int i=2,j=0; i<=m; i++)
{
while(j && s[j+1] != s[i]) j = nxt[j];
if(s[j+1] == s[i]) j++;
nxt[i] = j;
}
memset(f, 0, sizeof(f));
f[0][nxt[m]+1][0] = 1;
for(int i=0; i {
if(f[i][j][k])
{
add(f[i+1][j==m?nxt[m]+1:j+1][k+(j==m)], f[i][j][k]);
add(f[i+1][1][k], mul(f[i][j][k], 'z'-s[j]));
}
}
memset(g, 0, sizeof(g));
for(int i=1; i<=n; i++) for(int k=1; k<=i; k++)
{
add(g[i], mul(f[i-1][m][k-1]/(k/gcd(i,k)), i/gcd(i,k)));
}
for(int i=1; i<=n; i++) for(int j=i+i; j<=n; j+=i) if(g[j] != inf) g[j] -= g[i];
for(int i=m; i<=n; i++) if(g[i] == inf) return inf;
ll x = 0; for(int i=m; i<=n; i++) add(x, g[i]/i);
return x;
}
int main()
{
scanf("%d%lld%s", &n, &K, s+1);
m = strlen(s+1);
while(1)
{
ll x = calc();
if(K > x)
{
K -= x;
if(!inc()) puts("-1"), exit(0);
}
else
{
if(chk() && !--K) puts(s+1), exit(0);
s[++m] = 'a';
}
}
return 0;
}

在这个过程中,我们不仅解决了问题,也深化了对Lyndon串的理解。希望这篇文章能为你带来启发,激发你对算法世界的无限探索。


推荐阅读
  • 深入理解父组件与子组件的引用和访问
    本文详细介绍了如何在Vue.js中通过$children和$refs属性实现父组件对子组件的访问,并提供了具体的代码示例及最佳实践。 ... [详细]
  • LeetCode 540:有序数组中的唯一元素
    来源:力扣(LeetCode),链接:https://leetcode-cn.com/problems/single-element-in-a-sorted-array。题目要求在仅包含整数的有序数组中,找到唯一出现一次的元素,并确保算法的时间复杂度为 O(log n) 和空间复杂度为 O(1)。 ... [详细]
  • 2023 ARM嵌入式系统全国技术巡讲旨在分享ARM公司在半导体知识产权(IP)领域的最新进展。作为全球领先的IP提供商,ARM在嵌入式处理器市场占据主导地位,其产品广泛应用于90%以上的嵌入式设备中。此次巡讲将邀请来自ARM、飞思卡尔以及华清远见教育集团的行业专家,共同探讨当前嵌入式系统的前沿技术和应用。 ... [详细]
  • 本文介绍如何解决在 IIS 环境下 PHP 页面无法找到的问题。主要步骤包括配置 Internet 信息服务管理器中的 ISAPI 扩展和 Active Server Pages 设置,确保 PHP 脚本能够正常运行。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 探讨一个老旧 PHP MySQL 系统中,时间戳字段不定期出现异常值的问题及其可能原因。 ... [详细]
  • 国内BI工具迎战国际巨头Tableau,稳步崛起
    尽管商业智能(BI)工具在中国的普及程度尚不及国际市场,但近年来,随着本土企业的持续创新和市场推广,国内主流BI工具正逐渐崭露头角。面对国际品牌如Tableau的强大竞争,国内BI工具通过不断优化产品和技术,赢得了越来越多用户的认可。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 郑州大学在211高校中的地位与排名解析
    本文将详细解读郑州大学作为一所位于河南省的211和双一流B类高校,在全国211高校中的地位与排名,帮助高三学生更好地了解这所知名学府的实力与发展前景。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 优化ASM字节码操作:简化类转换与移除冗余指令
    本文探讨如何利用ASM框架进行字节码操作,以优化现有类的转换过程,简化复杂的转换逻辑,并移除不必要的加0操作。通过这些技术手段,可以显著提升代码性能和可维护性。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 电子元件封装库:三极管、MOS管及部分LDO(含3D模型)
    本资源汇集了常用的插件和贴片三极管、MOS管以及部分LDO的封装,涵盖TO和SOT系列。所有封装均配有高质量的3D模型,共计96种,满足日常设计需求。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
author-avatar
hfdljflkd_863
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有