CF17E Palisection

改进了一下 @\(\bf{ \color{black}\text{唐}\color{red} \text{一文}}\) 大佬的做法。

tags:

  • \(\text{strings}\)

  • \(\color{red}*2900\)

洛谷 CF

  • 给出一个字符串 \(s\),求 \(s\) 有多少对相交的回文子串(不考虑顺序)。

  • \(|s|\le 2\times 10^6\)

  • \(2.00\,\text{s}\,/\,125.00\,\text{MB}\)

考虑容斥,用回文子串对数减去不相交的。记 \(tot\) 表示回文子串个数,\(L_i\) 表示以 \(i\) 开头的回文子串个数,\(R_i\) 表示以 \(i\) 结尾的回文子串个数,则答案为:

\[\dfrac{tot\cdot (tot-1)}{2}-\sum\limits_{i=1}^{|s|} \left(R_i\cdot \sum\limits_{j=i+1}^{|s|} L_j\right) \]

简单解释一下,就是枚举左边回文子串的结尾位置,那么所有开头位置大于这个位置的回文子串与其不相交。

考虑如何求出 \(tot\),枚举中心 \(i\),分奇数、偶数长度讨论,可以发现若一个子串是回文串,那把它两端的字符去掉其仍然是回文串,即答案有单调性。

维护正反串哈希值,考虑二分 + 哈希求出出最长的奇数 / 偶数分别是第几个。记为 \(f0,f1\),那么它带来了 \(f0+f1\) 个回文子串。

而且可以发现,以奇数为例,对于 \([i-f0+1,i]\) 这些位置又可以作为当前回文串的左端点,相当于 \(L\) 区间 \(+1\)\([i,i+f0-1]\) 这些位置可以作为右端点,相当于 \(R\) 区间 \(+1\)

由于只有一次查询,而且还是在最后,考虑维护差分数组并前缀和,就可以求出 \(L_i,R_i\)

最后枚举 \(i\),维护一下 \(L\) 的后缀和直接算即可。

时间复杂度为 \(\mathcal{O}(|s|\log |s|)\),空间复杂度为 \(\mathcal{O}(|s|)\)

提交记录(\(\color{limegreen}\bf Accepted\) \(\boldsymbol{590\,\text{ms}\,/\,52008\,\text{KB}}\),含代码)

posted @ 2023-11-13 11:14  lzyqwq  阅读(23)  评论(0)    收藏  举报