给定长度为 \(n(1 \le n \le 2^{20})\) 的字符串 \(s\),问有多少种合法的拆分方式?一种合法的拆分方式:
- \(s = (AB)^iC(i > 0)\)其中 \(A,B,C\) 为非空字符串,\((AB)^i\) 为 \(i\) 个 \(AB\) 拼接的结果。
- \(F(A) \le F(B)\) \(F(s)\) 表示 \(s\) 中出现奇数次的字符数。
先忽略第二个条件。显然可以把 \(AB\) 看成一个整体(题目给了很强的提示),枚举 \(AB\) 的长度 \(len\),用 hash 判断每个 \(i\) 是否可行。
由调和级数可知,至多由 \(n \log n\) 个 \(i\)。每个 \(i\) 有 \(len - 1\) 种选法。
接下来考虑第二个条件,可以预处理出 \(s\) 有段后缀的 \(F_i\) ,然后将长度为 \(1 \sim len - 1\) 的 \(F\) 丢到数组里(表示 \(A\) 的选法),查询 \(F_{i\cdot len + 1}\) 对应的贡献即可。
因为 \(F \le 26\),直接暴力加贡献即可。(否则还要个树状数组,时间复杂度是 \(O( n\log n\log26)\))。
时间复杂度:\(O(n (\log n + 26))\)。
注意下常数能过,似乎有 \(O(n)\) 的扩展 KMP 做法。