[解题报告] [NOI2016]优秀的拆分
目录
题意
若一个拆分方式能把一个串表示为 \(AABB\) 的形式, 则称这个拆分为 "优秀的拆分".
给定一个串 \(S\), 求它所有子串的所有 "优秀的划分" 数量总和.
\(T\) 组数据, \( T \le 10,\ n \le 30000 \)
解法
首先可以想到在 \(AA\) 和 \(BB\) 之间的那个位置统计答案, 那么我们就需要对每个位置 \(i\) 算出以它为起点 / 终点的形如 \(AA\) 的串个数.
计算这个要用到一个 "撒点" 的套路.
具体来说就是枚举 \(AA\) 的长度 \(len\), 然后把原串 \(S\) 分为形如 \([1,len],\ [len + 1, 2len], \cdots, [klen + 1, n] \) 的若干个子串.
然后我们对相邻的子串分别求出它们的 \(LCP\) 和 \(LCS\) (最长公共前缀和最长公共后缀).
然后稍微画一下就可以找出哪些位置可以作为长度为 \(2len\) 的 \(AA\) 串的起点或终点, 对于两个相邻的子串来说, 这些点会构成一个区间, 所以用差分实现一下区间加即可.
对于每个 \(len\), 处理一次的复杂度是 \(O(\frac{n}{len})\) 的, 所以总复杂度为 \( O(\sum_i \frac{n}{i}) = O(n\log n) \).
然后求 \(LCP\) 和 \(LCS\) 用 SA 或者 SAM 即可. (当然二分加哈希也不是不可以, 不过就是多了个 \(\log\).)
代码
|
|