文章目录
简介
其实不太清楚这个应该叫什么,知道的同学可以麻烦告知我。
众所周知,一个串的border数量是 O ( n ) O(n) O(n)的,但是他们可以用 O ( l o g n ) O(logn) O(logn)段等差数列表示。
这个东西叫做Border Series,然后把他和回文串结合起来放在PAM上使用,就是本文说的Palindrome Series了。
这东西代码实际非常短,使用的时候,只需要修改3行(DP转移部分)。
背景知识
弱周期定理
这里不详细展开讲,这是一个well known的定理,在使用Series相关的科技时会反复用到,可以自行搜索了解。
Border Series
一个串的长度在 [ 2 k , 2 k + 1 ) [2^k,2^{k+1}) [2k,2k+1)范围内的border长度构成等差数列,证明使用上面的弱周期定理,可以参考2019国集论文等很多资料,不讲。
Palindrome Series
考虑一个回文串 S S S的后缀 T T T,则有: T T T是回文串与 T T T是 S S S的border 等价。再结合上面的Border Series,即可得到一个推论:一个回文串的所有回文后缀可以表示为 O ( l o g n ) O(logn) O(logn)段等差数列。设法对每段等差数列进行维护,就可以 O ( l o g n ) O(logn) O(logn)枚举所有回文后缀,这就是Palindrome Series做的事情。
PAM
前置技能点:Palindrome Automaton,回文自动机。
例题:CF 932G
题意
转化之后的题意为:给一个串 S ( ∣ S ∣ ≤ 1 0 6 ) S(|S| \le 10^6) S(∣S∣≤106),规定一个 S S S的分割是合法的当且仅当:分割的每一部分都是偶回文串。
求合法的分割方案数。
题解
暴力DP
很容易直接想到暴力DP的办法:设 f [ i ] f[i] f[i]表示将串 S [ 1 , i ] S[1,i] S[1,i]进行分割的方案数。
初始化 f [ 0 ] = 0 f[0] = 0 f[0]=0,转移为
f [ i ] = ∑ 1 ≤ j < i f [ j ] ⋅ [ S [ j + 1 , i ] 是 偶 回 文 串 ] f[i] = \sum_{1 \le j < i} f[j] \cdot [S[j+1,i]是偶回文串] f[i]=1≤j<i∑f[j]⋅[S[j+1,i]是偶回文串]
也就是我们需要枚举所有 S [ 1 , i ] S[1,i] S[1,i]的(偶)回文后缀。使用PAM,全 a a a串的复杂度为 O ( n 2 ) O(n^2) O(n2),不能通过。
使用Palindrome Series优化DP
符号约定
l e n [ i ] len[i] len[i] 表示节点代表的回文串长度
f a i l [ i ] fail[i] fail[i] 表示节点的失配指针,即最长的回文后缀,即最大border。
d i f f [ i ] = l e n [ i ] − l e n [ f a i l [ i ] ] diff[i] = len[i] - len[fail[i]] diff[i]=len[i]−len[fail[i]] ,表示一个节点和他最大border长度的差,即所在的等差数列的公差。
a n c [ i ] anc[i] anc[i] 表示节点所在等差数列的首项位置,即从 i i i开始往根走,保证 d i f f diff diff值都相同,最终走到的点。
g [ i ] g[i] g[i] 维护每个点到链顶的信息,维护的范围是 ( l e n [ a n c [ i ] ] , l e n [ i ] ] (len[anc[i]],len[i]] (len[anc[i]],len[i]],公差 d = d i f f [ i ] d = diff[i] d=diff[i]。
f [ i ] f[i] f[i] 表示 D P DP DP值,即将串 S [ 1 , i ] S[1,i] S[1,i]进行分割的方案数。
转移方法
l e n , f a i l , d i f f , a n c len,fail,diff,anc len,fail,diff,anc都可以在构造 P A M PAM PAM的过程中求得。
重点在于 f , g f,g f,g的相互转移。
根据定义: f [ i ] = ∑ p g [ p ] f[i] = \sum_{p} g[p] f[i]=∑pg[p],其中 p p p是在PAM上跳到的点,跳的方式是每次从 p p