P4143 采集矿石 题解

题目传送门

  • 给出字符串 s,以及数组 a1a|s|

  • 定义一个子串的排名为:字典序比它大的本质不同的子串个数 +1

  • 定义一个子串 s[l,r] 的权值为 i=lrai

  • 求有多少个子串的排名等于权值。

  • |s|105,0ai1000

首先对 s 进行后缀排序,然后考虑每一个左端点 l,不难发现随着右端点 r 的增大,子串的排名单调递减,权值单调不降。

所以可以二分出满足条件的最小 / 大右端点。

考虑如何求出一个子串 t 的排名。可以用本质不同子串数减去比它小的。

前半部分运用经典结论即为 i=1n(|s|sai+1heighti),我们考虑如何求比它小的本质不同子串数。

可以二分出以这个子串为前缀的后缀排名区间 [L,R]答案即为排名为 [1,L) 的后缀带来的本质不同子串个数。

  • 充分性:

    若一个子串 str 在排名为 [1,L) 的后缀中作为前缀出现,那么这个后缀 s[i,|s|]s[l,|s|]LCP 长度一定小于 |t|。即两个后缀可以在第 |t| 个位置之前可以找到不相同的位置。而由于 s[i,|s|] 这个后缀排名更小,在这个位置一定 s[i,|s|] 这个后缀小于 s[l,|s|]

    考虑 str 是否跨过这个位置,若不是,则在前 |str| 位两串相同,第 |str|+1str 为空,字典序极小。

    若跨过,则 str 在这个位置小于 t

  • 必要性:

    考虑这两个子串第一次不同是在某个位置,这个位置一定在两个后缀中。

正确性证好了。这个东西也是考虑每个后缀带来的本质不同子串。即可以这么求:

i=1L1(|s|sai+1heighti)

于是做完了。时间复杂度为 O(|s|log2|s|),空间复杂度为 O(|s|)

提交记录 代码

posted @   lzyqwq  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示