具体可以看这篇论文:https://arxiv.org/pdf/1403.2431v2.pdf
这篇文章其实是半搬该论文半搬别人博客的
最小回文分解:Minimum Palindromic Factorization
我们令
P
L
(
S
)
PL(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
PL(S[1..i])−1⩽PL(S[1...i+1])⩽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]
S1,S2...Sl−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]
S1,...,Sl−1,S[h],S[h+1...i]
接下来,我们会给出一个时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间为 O ( n ) O(n) O(n)的算法。
引理1:
如果y是回文串x的前缀并且y是回文串,那么y是x的border。
引理2:
如果y是x的border并且
∣
x
∣
⩽
∣
2
y
∣
|x|\leqslant |2y|
∣x∣⩽∣2y∣,那么x是回文串当且仅当y是回文串。
引理3:
如果y是回文串x的前缀,那么
∣
x
∣
−
∣
y
∣
|x|-|y|
∣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∣⩾∣v∣
证明:如果不成立,那么u可以成为y的最小循环节,与v为y的最小循环节矛盾。
(2)
i
f
∣
u
∣
>
∣
v
∣
,
那
么
∣
u
∣
>
∣
z
∣
if\ |u|>{}|v|,那么|u|>|z|
if ∣u∣>∣v∣,那么∣u∣>∣z∣
证明:可以注意到,如果题干成立,那么v是u的一个前缀,也是x的一个前缀。
我们可以将x表示成vw
因为
∣
u
∣
>
∣
v
∣
|u|>|v|
∣u∣>∣v∣,那么
∣
w
∣
>
∣
y
∣
|w|>|y|
∣w∣>∣y∣。
采用反证法,如果
∣
u
∣
⩽
∣
z
∣
|u|\leqslant |z|
∣u∣⩽∣z∣
那么
∣
w
∣
=
∣
z
u
∣
⩽
2
∣
z
∣
|w|=|zu|\leqslant 2|z|
∣w∣=∣zu∣⩽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
if ∣u∣=∣v∣,then u=v
显然。
根据引理4,我们可以发现一个回文串border之间的差递减,且可以划分成
O
(
l
o
g
n
)
O(log_{n})
O(logn)个差相等的部分。
以下参考自博客: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}
ancu={ancfailu,(lenu−lenfailu==lenu−lenfailfailu)u(otherwise)
如果我们不停执行
u
=
f
a
i
l
a
n
c
u
u=fail_{anc_u}
u=failancu,那么我们至多执行
O
(
l
o
g
n
)
O(log_n)
O(logn)次
有点树连剖分的感觉。
那么我们令
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 \}
Su={v∣ancv=ancu,v=fail(fail(...fail(u)))}
在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 \}
fi=minvϵSu{fi,fi−lenv+1}
其中
S
u
S_u
Su最多
l
o
g
i
log_i
logi个。
注意到,所有在
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
i−(lenu−lenfailfailu),failu处转移到的v会在i,u处转移到。且i,u多转移到的便是
f
i
−
l
e
n
a
n
c
u
f_{i-len_{anc_u}}
fi−lenancu
当然,前提是
a
n
c
u
≠
u
anc_u\neq u
ancu̸=u.
那,我们记录rem_u为当前经历到u的最后的i转移到的v的最小值。那么当前i经历到的u的
r
e
m
u
rem_u
remu需要根据
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}}
remfailuandfi−lenancu来更新(当然,前提也是
a
n
c
u
≠
u
anc_u\neq u
ancu̸=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ϵ(i−(lenu−lenfailu),i),i不会经过
f
a
i
l
u
fail_u
failu
证明略。主要抓住:
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}}
lenu−lenfailu=lenfailu−lenfailfailu
具体代码可以看CF906E。不过它那里的要求和最小回文分解的要求有些出入。
完结撒花!