详解马拉车算法中的半径数组计算方法

本文深入解析Manacher算法,一种求解最长回文子串问题的高效算法,时间复杂度为O(n)。文章通过对比O(n^2)的传统算法,详细阐述了Manacher算法的原理,包括辅助指针id和mx的使用,以及如何利用回文串特性降低时间复杂度。通过实例解释了算法的执行流程,并提供了Python代码实现。

最近有个朋友给我介绍tx的面经时提到了最长回文子串问题,这才知道原来还有时间复杂度为O(n)的解法——Manacher算法,于是去翻了翻博客,发现对于半径数组p的讲解都非常难懂,为了节约以后自己复习算法的时间,特地写一篇博客来好好理解这一部分的内容。在浏览本文前,请确保自己已了解O(n2)的算法,因为Manacher算法本质上是对于O(n2)算法的一种优化
先给出我学习这个算法时主要参考的博客:https://blog.youkuaiyun.com/happyrocking/article/details/82622881

一、两个辅助指针

在计算半径数组p时,一般会涉及到两个指针:id和mx,这两个指针是根据已发现的右边界位置最大的回文子串来定义的(请区分实际的最长回文子串和”已发现的右边界位置最大的回文子串“),其中id是上述回文子串的中心位置,mx是上述回文子串的右边界位置(也就是末尾的位置)。
举个例子:
假设字符串s="#g#o#o#g#l#e#"

位置i 1 2 3 4 5 6 7 8 9 10 11 12 13
s[i] # g # o # o # g # l # e #

和O(n^2)的算法类似,我们每次以位置i为中心寻找最长回文子串。
当i=4时,已发现的右边界位置最大的回文子串是“#o#”,我们可以更新id=4,mx=5。
当i=5时,已发现的右边界位置最大的回文子串是“#g#o#o#g#”,我们更新id=5,mx=9。

二、利用回文串特性降低时间复杂度

可能有人会有疑问:既然还是要像O(n2)的算法一样以位置i为中心寻找最长回文子串,那是怎么做到把时间复杂度降低为O(n)的呢?其关键就在于mx——当i<mx时,我们利用回文串的特性来避免“以位置i为中心寻找最长回文子串”这一操作。如果i<mx时每次操作的复杂度是O(1),那么一旦mx为原字符串最末端,那么之后的总操作复杂度最多也就是O(n);而mx扩展到最末端所需的时间复杂度最多也是O(n),所以整个算法的时间复杂度就是O(n)。
以上说法只是为了便于理解,非常不严谨,真正的推导过程请自寻查找。
那么接下来的重点就很明显了:当i<mx时,如何利用回文串的特性来避免“以位置i为中心寻找最长回文子串”这一操作呢?很多博客都是用下面这张图来讲的(包括我主要参考的那篇):

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值