专栏文章

[OOI 2023] 字符串问题

P13531题解参与者 4已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@miomt688
此快照首次捕获于
2025/12/02 21:46
3 个月前
此快照最后确认于
2025/12/02 21:46
3 个月前
查看原文
本题解为官方题解的 AI 中文翻译。
我们记 count(h)count(h) 为字符串 hh 的所有子串中,出现在集合 SS 里的子串数量。对于每个询问,我们需要计算 count(h[li,ri])count(h[l_i, r_i])。令 pref[i]=count(t[0:i))pref[i] = count(t[0:i)),即 tt 的长度为 ii 的前缀中,出现在 SS 中的子串数量。令 suf[i]=count(t[i:t))suf[i] = count(t[i:|t|)),即从位置 ii 开始的后缀在 SS 中出现的子串数量。
可以发现,pref[r]+suf[l]count(t)pref[r] + suf[l] - count(t) 等于 count(t[l,r])count(t[l, r]),再减去那些属于 SS 的子串,这些子串在 tt 中的起点早于 ll,终点晚于 rr。如果不存在这种“跨界”子串,那么答案就很容易求出,所有需要的 pref[l]pref[l]suf[r]suf[r] 都可以通过 Aho-Corasick 算法计算得到。
如果存在上述“跨界”子串,则对于询问 t[l,r]t[l, r],我们需要找到这样一个 SS 中的子串 sis_i,它在 tt 中的出现起点早于 ll,终点晚于 rr。在所有满足条件的 sis_i 中,选择右端点最靠左的那个。设其为 sis_i。注意,t[l,r]t[l, r]sis_i 的一个子串,记作 si[l,r]s_i[l', r']。同时,sis_i 中不存在起点早于 ll'、终点晚于 rr'且属于 SS 的子串(否则 t[l,r]t[l, r] 会被更靠右的 SS 中子串覆盖)。因此,我们可以对 sis_i 应用前缀和后缀的原理,递归求解。
为了在询问 t[l,r]t[l, r] 时找到合适的 sis_i,我们可以用扫描线遍历 tt。利用 Aho-Corasick 算法,对于每个位置 ii,找到以 ii 结尾的、属于 SS 的最长子串(记为 sjs_j)。同时,在一个堆或 set 结构中维护所有右端点不超过 ii 的询问的起点。对于每个起点晚于 sjs_j 起点的询问,sjs_j 都是合法的覆盖子串。所有这些询问随后从堆中移除。
因此,最终方案需要构建正向和反向的 Aho-Corasick 自动机,并用扫描线遍历 tt,配合堆维护查询。总复杂度为 O(S+t+mlogm)O(S + |t| + m \log m)

评论

4 条评论,欢迎与作者交流。

正在加载评论...