【动态规划】北航程序设计竞赛决赛B题

本文介绍了一种解决特定字符串问题的方法,即求解字典序第k小的子串。通过逐步确定答案中每个字符的位置,并考虑字符重复的情况,使用动态规划优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 决赛那天感觉确实没发挥好。本来有机会逃离三题大队的。结果中途很多人搞了几何构造题,忍不住跟风。事实证明以我的想象力果然搞不出来。还不如专心搞搞B这题。
 B的题意很简单,给一个长度不超过5000的字符串,字符集大小不超过5000,求字典序第k小的子串(子串可以不连续),k规模不超过子串总数以及1E18。
 先考虑每个字符都不同的情况,很容易想到一个一个把答案的字符定下来。我们每一次求出下一步接字符a[i]的子串个数,也就是2n−i2^{n-i}2ni,那么从小到大枚举字符值x,找到第k个字符串所在的那个x即可,再让k减去这一步小于x的子串总数,进入下一步。
 出现重复字符时,2n−i2^{n-i}2ni还需要乘上一个累计值g,这个值取决于a[i]之前出现的已有字符串ans的总数。用dp来记录以i结尾的字符串ans总数,这个累计值就是dp数组的前缀和。注意如果g[n]>=k则下一个字符是空的,直接退出就好了。
 由于题目没有放在OJ上,以下代码只是随便打打,题解的解释之后也会进一步补充。
 自己以后思路还需要放清晰,不能在比赛的时候慌乱。

#include<cstdio>
#include<algorithm>
using namespace std;
using LL=long long;

int T,n,m,k,a[5005],ans[5005];
LL dp[5005],g[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值