Manacher
O(n)求最长回文串,manacher应该是比较好打的一种吧。
进入正题
manacher算法,中文也叫马拉车,下文将用马拉车来称呼它。
为了节约代码量,不讨论长度奇偶问题,马拉车在原串中添加字符(必须是原串字符集里不存在的)。
同时为了使算法不越界,头尾也要添加不同的字符
像是这样
类型 | 字符串 |
---|---|
原串 | abcdef |
马拉车修改后 | $#a#b#c#d#e#f#@ |
接下来,我们需要引入几个东西了。
p[i]
p
[
i
]
表示的是以第i个字符为中心的最长回文串半径。
mx
m
x
当前所有回文串中延伸得最远的回文串的右边界
id
i
d
mx所属的回文串的中心
开始分类讨论
如果
i
i
在mx之外的话,直接暴力。
如果在mx之内,之前的计算结果就能派上用场了
考虑回文串的性质,在i关于id对称的位置,是与i相同的,记它为
继续分类讨论
如果si为中心的最长回文串范围没有越过id的范围
仔细思考一下会发现,
Psi=Pi
P
s
i
=
P
i
,这应该不难理解,不再作解释。
反之,如果和id的边界刚好接触或是超过。
那么,
Psi
P
s
i
不一定等于
Pi
P
i
但是,可以保证
Pi⩾mx−i
P
i
⩾
m
x
−
i
所以
Pi
P
i
应从
mx−i
m
x
−
i
开始暴力计算。
复杂度分析
空间复杂度不用说,P数组,
O(n)
O
(
n
)
;
时间复杂度是
O(n);
O
(
n
)
;
考虑第一种情况,一定是上一个的回文串的
Pi=1
P
i
=
1
这时暴力匹配,如果匹配到了比较长的,那后面一大段都是
O(1)
O
(
1
)
匹配,
如果
Pi=1
P
i
=
1
,又是第一种。
均摊
O(n);
O
(
n
)
;