如何优雅地求区间本质不同回文串
如何优雅地求区间本质不同回文串
0. $O(n^2)$
直接暴力。一点都不优雅。
1. $O(n\sqrt n\Sigma)$
允许双向加的回文树,再套一个(在线)莫队即可。
太拉了,还难写。
2. $O(n\log^2 n)$
考虑离线,依次加入字符,维护每个 $i$ 作为左端点的答案。
考虑维护差分数组,这样每次答案是一段后缀和。
思考一种暴力思路:在回文树上,对于每个串 $s_j$ 记录最晚出现位置 $p_j$。
设一次加入后字符串长度为 $n$,本质上是对于回文树上这个字符串到根路径上所有字符串 $s_j$,在 $p_j$ 处 $-1$,在 $n-|s_j|$ 处 $+1$,并将 $p_j$ 改为 $n-|s_j|$。
直接做显然会被卡掉。
考虑一个事情,每个回文串的 border 可以表示为 $O(\log n)$ 个等差数列。注意到一个性质:对于回文串 $s$,如果存在长度 $q(q>\frac{|s|}2)$ 的回文前缀,那么一定存在 $|s|-q$ 的周期。换句话说,如果存在长度为 $p,q(p>q>\frac{|s|}{2})$ 的回文前缀,那么一定存在 $2q-p$ 是回文前缀。
所以任意两个等差数列都有前者的首项大于后者的末项的两倍。
并且观察到一个事实:对于等差数列 $s_i=u^i+s_0$,一定有 $p_i=-i|u|+p_0$。换句话说这个字符串的贡献是当前左端点到后一项的左端点。
贡献和的并就是最后一个位置为右端点,整个区间上一次出现位置为左端点的区间。
换句话说,我们只需要贡献所有不存在长度 $>\frac{|s|}2$ 的回文串后缀的后缀 $s$ 即可。这样的 $s$ 最多 $O(\log n)$ 个,具体求出可以直接在回文树上预处理。
复杂度 $O(n\log^2 n)$。
3. $O(n\log n)$
对于任意字符串 $s$,如果 $s$ 不是整循环串,那么 $s$ 的所有循环位移中至多只有 $2$ 个是回文串。可以想象一个定义在圆上的函数,如果有两条不重合的对称轴,那么一定是一个周期函数。
考虑原串的 Runs $(l,r,p)$,显然 $s[l:l+p-1]$ 不是整循环串(Runs 的定义),那么至多只有 $2$ 个极长整循环周期为 $p$ 的回文串。
可以发现上述算法中,每个极长整循环的回文串只有在循环节处会产生 $O(\log n)$ 的处理代价。而所有极长整循环的回文串指数之和不超过 Runs 的指数之和的两倍,故是 $O(n)$ 的。
所以上面那个算法其实是 $O(n\log n)$ 的。