CF1037H Security 做题记录

搬的学习笔记,之前没想过要新开一篇。

题目传送门(CF)

  • 给出一个字符串 s,有 q 次询问,第 i 次询问给出 li,ri,ti,求一个字典序最小的字符串 str,使得它是 s[li,ri] 的子串,且 str>ti

  • |s|105i=1q|ti|,q2×105

|LCP(str,ti)|=lstr>ti 当且仅当 strl+1>til+1,为了使 str 尽量小,我们希望 l 尽量大

证明很简单,假设有一个串 T 满足 LCP(T,ti)=L<l,则 LCP(str,T)=L,且 TL+1>strL+1,因此 T>str,所以 |LCP| 大的字符串字典序更小

先将 s 和所有 ti 中间用奇怪字符拼接成大串 S,这样不改变任意两个后缀的 LCP。然后做一遍后缀排序,求出 sa,rk,height 数组以及维护 ST 表辅助求后缀之间的 |LCP|

对于每一组询问,考虑枚举 l(0lrili) 以及下一位拼上什么字符 c,满足 c>til+1(一定是仅拼上一个字符,因为空字符字典序最小)。可以先二分 + ST 表求出与 tiS 中的后缀的 |LCP| 至少为 l 的后缀排名区间 [L,R]。那么在 LCP 末尾拼上一个字符 c 后(记这个字符串为 p),以 p 为前缀的后缀的排名仍然是一个连续的区间。由于后缀排序过,因此 [L,R] 排名区间内的后缀的第 l+1 位的字符一定单调不减

考虑继续二分出这个连续区间 [ql,qr],可以二分找到最小的排名 mn 使得 Ssamn+lc 以及最大的排名 mx 使得 Ssamx+lc。则 ql=mn,qr=mx。若不存在 [ql,qr] 这个区间,则跳过。

我们要求 s[li,ri] 中是否存在一个子串 strp 为前缀,相当于求 suflisufril 这些后缀中,是否存在一个后缀 sufj 使得 qljqr。至此原问题转化成了二维数点,用主席树维护即可。

可以从小到大枚举 c,对于枚举的 l,我们找到一个最小的字符 c 满足条件之后,即可停止当前 l 的枚举。因为要求字典序最小。

对于多种 l 的答案,上面已经说过,选最大的那一种。

默认 |S|,q 同阶,时间复杂度为 O(|Σ|(i=1q|ti|)log|S|+|S|log2|S|),空间复杂度为 O(|S|log|S|)。由于不是瓶颈,后缀排序部分未使用基数排序优化。

提交记录(含代码)

posted @   lzyqwq  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示