最小回文分解学习笔记

具体可以看这篇论文:https://arxiv.org/pdf/1403.2431v2.pdf
这篇文章其实是半搬该论文半搬别人博客的
最小回文分解:Minimum Palindromic Factorization
我们令 P L ( S ) PL(S) 表示S的最小回文分解。
那么令len为S的长度。

我们有一个不等式:
P L ( S [ 1.. i ] ) 1 P L ( S [ 1... i + 1 ] ) P L ( S [ 1.. i ] ) + 1 PL(S[1..i])-1\leqslant PL(S[1...i+1])\leqslant PL(S[1..i])+1
证明:
后半部分显然,考虑如何证明前半部分。
如果S[1…i+1]的回文划分是 S 1 , S 2 . . . S l 1 , S [ h . . . i + 1 ] S_{1},S_{2}...S_{l-1},S[h...i+1]
那么我们很明显可以将S[1…i+1]划分成 S 1 , . . . , S l 1 , S [ h ] , S [ h + 1... i ] S_{1},...,S_{l-1},S[h],S[h+1...i]

接下来,我们会给出一个时间复杂度为 O ( n l o g n ) O(nlogn) ,空间为 O ( n ) O(n) 的算法。

引理1:
如果y是回文串x的前缀并且y是回文串,那么y是x的border。

引理2:
如果y是x的border并且 x 2 y |x|\leqslant |2y| ,那么x是回文串当且仅当y是回文串。

引理3:
如果y是回文串x的前缀,那么 x y |x|-|y| 是x的循环节当且仅当y是个回文串。
并且 x y |x|-|y| 是x的最小循环节当且仅当y是x的最长回文前缀。

引理4:
x是个回文串。y是x的最长回文前缀。z是y的最长回文前缀。
那么x可以表示成uy,y可以表示成vz。
(1) u v |u|\geqslant |v|
证明:如果不成立,那么u可以成为y的最小循环节,与v为y的最小循环节矛盾。
(2) i f   u > v u > z if\ |u|>{}|v|,那么|u|>|z|
证明:可以注意到,如果题干成立,那么v是u的一个前缀,也是x的一个前缀。
我们可以将x表示成vw
因为 u > v |u|>|v| ,那么 w > y |w|>|y|
采用反证法,如果 u z |u|\leqslant |z|
那么 w = z u 2 z |w|=|zu|\leqslant 2|z|
注意到z是w的border。(后缀显然,前缀因为y=vz为vw的前缀)
那么根据引理2,w是回文串。那么w是x的前缀。
这样,y是x的最长回文前缀不成立。
(3) i f   u = v , t h e n   u = v if\ |u|=|v|,then\ u=v
显然。
根据引理4,我们可以发现一个回文串border之间的差递减,且可以划分成 O ( l o g n ) O(log_{n}) 个差相等的部分。

以下参考自博客:https://www.cnblogs.com/King-George/p/9612816.html
到这里,我们考虑如何求出最小回文分解。
我们建出回文树。
a n c u = { a n c f a i l u , ( l e n u l e n f a i l u = = l e n u l e n f a i l f a i l u ) u ( o t h e r w i s e ) anc_{u}=\begin{cases} & \text anc_{fail_u},(len_{u}-len_{fail_u}==len_u-len_{fail_{fail_u}})\\ & \text u(otherwise) \end{cases}
如果我们不停执行 u = f a i l a n c u u=fail_{anc_u} ,那么我们至多执行 O ( l o g n ) O(log_n)
有点树连剖分的感觉。
那么我们令 S u = { v a n c v = a n c u , v = f a i l ( f a i l ( . . . f a i l ( u ) ) ) } S_{u}=\left \{v|anc_{v}=anc_{u},v=fail(fail(...fail(u)))\right \}
在dp转移时每次会有, f i = m i n v ϵ S u { f i , f i l e n v + 1 } f_{i}=min_{v\epsilon S_u}\left \{f_{i},f_{i-len_v}+1\right \}
其中 S u S_u 最多 l o g i log_i 个。
注意到,所有在 i ( l e n u l e n f a i l f a i l u ) , f a i l u i-(len_u-len_{fail_{fail_u}}),fail_u 处转移到的v会在i,u处转移到。且i,u多转移到的便是 f i l e n a n c u f_{i-len_{anc_u}}
当然,前提是 a n c u u anc_u\neq u .
那,我们记录rem_u为当前经历到u的最后的i转移到的v的最小值。那么当前i经历到的u的 r e m u rem_u 需要根据 r e m f a i l u a n d f i l e n a n c u rem_{fail_u}and f_{i-len_{anc_u}} 来更新(当然,前提也是 a n c u u anc_u\neq u )。
当然这里,我们需要证明对于 i ϵ ( i ( l e n u l e n f a i l u ) , i ) i\epsilon(i-(len_u-len_{fail_u}),i) ,i不会经过 f a i l u fail_u
证明略。主要抓住: l e n u l e n f a i l u = l e n f a i l u l e n f a i l f a i l u len_u-len_{fail_u}=len_{fail_u}-len_{fail_{fail_u}}
具体代码可以看CF906E。不过它那里的要求和最小回文分解的要求有些出入。

完结撒花!

猜你喜欢

转载自blog.csdn.net/ezoilearner/article/details/84851672