manacher算法

manacher算法

若要计算一段字符串中的最长回文段的长度,可能会有一下想法

暴力大法

说什么,就求什么。两层for循环分别枚举出当前字符段的起始点,然后再用一次循环判断是否可行。但是很明显,这是一种o(n3)算法,根本上不了台面

暴力的稍微优化版

既然对于每一个循环节,总会有一个对称轴,那么其实只要枚举这个对称轴,然后判断对于每一个对称轴可扩展出的最远距离即可。

但是这个方法又两大缺点:
1. o(n2)算法,虽然有了提升,但还不够
2. 对于奇数个字符的回文段,其对称轴再某一个字符上;但是对于偶数个字符的回文段,其对称轴就不再某一个字符上,而是在两个字符中间。这样的话枚举的时候就需要分两次分局,操作繁琐。

manacher算法

这个时候,这个及其优的算法——马拉车算法就能排上用场了。
这个算法可以在o(n)的线性时间内计算出一个字符串最长回文段的长度。

具体实现思路
因为暴力算法的改进版中存在一个:奇数回文段和偶数回文段需要分别计算的尴尬,那么为了解决这个问题,manacher就在每一个字符之间加了一个’#’,用以分割。

例子:
原字符串: a b c d
转换后的字符串:@ # a # b # c # d # !

解释一下:
‘#’指字符串两个字符之间的占格字符,并不是非要’#’不可,只要是一个原字符串中没有出现过的字符即可
‘!’、‘@’是用来记录一个字符串的开头结尾的,同样要求由一个原字符串中没有出现过的字符来充当,并且前后要求不同才能区分出来。

这么处理的好处时,假如我们知道了任何一个点,以该点为对称轴向右侧可扩散到的,符合回文串条件的最远距离,那么只要将这个长度-1便是以该点为对称轴向右侧可扩展到的最远距离。

那么,下一步,我们就需要在线性时间内求出这么一个数组(l[]);

…….编不下去了,下面有一些对于理解很重要的图,还是直接附上另一位大佬的文章地址吧:

https://segmentfault.com/a/1190000008484167

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值