题意简述
给你一个长度为 $n$ 的数组 $a$,问你有多少个区间,满足:
- 长度为偶数
- 前一半和后一半循环同构
$n\le 5000,a_i\le 5000$
思路
两个串 $a,b$ 循环同构 ,那么一定可以把 $a$ 分成两个串 $u,v$ 接起来,然后把 $b$ 表示成 $v,u$ 的形式。
就比如 $a=\texttt{“abcde”},b=\texttt{“cdeab”}$,那么 $a=\texttt{“ab”+”cde”},b=\texttt{“cde”+”ab”}$。
然后现在这两个串相邻了,也就是有一段连续的 $uv|vu$ 的形式。考虑枚举中间这个划分线,然后计算两边有多少满足条件的。这也许能用哈希水过,但是我们要想一个正经办法(*^▽^*)
一般我们遇到这样的“分块回文” 的问题,都是怎么做的呢⊙(・◇・)?
联想一下 codeforces 932G 这个题,我们可以把前面一半的 $uv$ 反过来,然后一个隔一个的插入到后半边的 $vu$ 里面去。这样插入完就会变成两个长度为偶数的回文串拼在一起啦 (/≧▽≦/)
关于它为啥会变成这样
先考虑一个串的情况。现在有一个 $u$,假设它由三个字符 $a,b,c$ 构成。我们把它反过来,然后一个隔一个的插入,变成:
$\color{red} c\color{black}a \color{red} b \color{black} b \color{red} a \color{black} c$
新插入的用红色表示,原来就有的用黑色表示。然后我们发现它变成了一个回文串!
容易归纳证明,无论它长度多少,这样子做总会变成一个回文串。
然后考虑两个串 $u,v$ 拼一块的情况。我们把 $u+v$ 反过来,一个隔一个的插入到 $v+u$ 中,会变成什么呢?
设 $s’$ 是 $s$ 反过来的串。然后显然 $(u+v)’=v’+u’$。我们把它插入到 $v+u$ 中之后,前面 $|v|$ 个串会先变成一个长度为 $2|v|$ 的回文串,后面还有 $|u|$ 个串,会变成长度为 $2|u|$ 的回文串。于是总体就变成了一个长度为 $2|v|+2|u|$ 的两个偶数长度回文串。
举个例子,$u=\texttt{“ab”},v=\texttt{“cd”}$,这样插入完之后变成 这样:公式炸了,点我
它等于 $\texttt{“dccd”}+\texttt{“baab”}$。
(你们可能不知道这公式有多难打,就为了举个形象的例子… 唉o(╥﹏╥)o)
然后我们只需要用 Manacher 统计一下有多少个这样的回文串即可(~ ̄▽ ̄~)
设 $pre[i]$ 表示从 $i$ 往前最多能跳多少长度,使得跳过的部分是回文串。然后 $f[i]$ 是回文中心。
用 $last$ 记录上一个回文前缀的位置。当前位置在 $i$ ,如果 $[last,i]$ 是个回文串,或者 $[i-pre[i]+1,i]$ 是个回文串,那么当前的 $i$ 就是合法的~☆,答案 ++。
那么如何判断 $[l,r]$ 是不是回文串呢⊙(・◇・)?设 $mid=(l+r)/2$,看看是否满足 $f[mid]\ge (r-l+1)/2$ 即可。
代码
1 |
|