CF1483F - Exam
CF1483F - Exam
题目大意
给定 \(n\) 个不同串 \(s_i\) ,令 \(s_i\sub s_j\) 表示 \(s_i\) 是 \(s_j\) 的子串
求所有二元组 \((i,j)(i\ne j)\) 满足
\(s_i\sub s_j,\nexists k\ne i,k\ne j,s_i\sub s_k\sub s_j\)
分析
首先可以说明答案是 \(O(\sum |s_i|)\) 级别的
对于每个 \(s_j\) 考虑其枚举 \(r\) 作为 \(s_i\) 的右端点,则 \(s_i\) 只有最长的一个会贡献答案
故每个右端点最多对应一个 \(s_i\)
一般情况下,判断子串相同的问题我们需要 \(\text{SAM}\)
但是鉴于这道题实际上需要判别的子串只有 \(n\) 个,而维护匹配只需要 \(\text{AC}\) 自动机,所以不需要 \(\text{SAM}\)
那么可以在 \(\text{AC}\) 自动机上预处理每个匹配节点在 \(\text{fail}\) 树上最近的有效祖先
即对于每个右端点找到了最长的 \(s_i\)
可以对于找到的 \(s_i\) 简单去重,但是仍然存在以下多余计算
- \(s_i\) 所对应的 \([l,r]\) 被某一个 \(s_i'\) 对应的 \([l',r']\) 包含的情况,可以 \(O(n)\) 判断区间包含干掉
2.一个 \(s_i\) 在这个位置被计算,但是实际上在其他位置被包含
实际上,这只需要判断 \(s_i\) 每一次被出现是否都是有效的即可
可以用树状数组+ \(\text{dfs}\) 序维护 \(s_i\) 出现的次数
时间复杂度为 \(O((\sum |s_i|)\log (\sum |s_i|))\) ,空间复杂度为 \(O((\sum |s_i|)|\Sigma|)\)
1 | const int N=1e6+10,INF=1e9+10; |