算法练习day18——190409(Manacher)

1.Manacher算法

一个串中,找到最长的回文子串。

1.1 暴力解决

得解决长度为奇数的回文和长度为偶数的回文。

1.1.1 奇回文

  • i位置自己肯定构成回文;长度为1
  • i+1位置和i-1位置相不相等?相等,构成回文。长度为3
  • i+2位置和i-2位置相不相等?相等,构成回文。长度为5

1.1.2 偶回文

1.1.1 中的方法不适用

1.1.3 解决方法

向字符串的开头、中间和结尾加东西。

既有奇回文:11311

又有偶回文:11

处理:

然后计算每一位的回文长度:

最终结果是:11/2=5

此方法适用于奇回文和偶回文。

添加的字符无论啥都可以。因为添加的字符不会和原字符串中的字符进行比较,只是和添加的字符比较(实轴永远和实轴比较,虚轴和虚轴比较)。

时间复杂度:O(N^{2})

2.概念

2.1 回文直径

回文半径

在Manacher算法中,需要准备一个数组——回文半径数组。存以每个位置为中心的情况下,可括出来的回文半径的长度。

加速:数组后面的位置的值能否利用前面的值,减少计算,实现加速。

2.2 最右回文右边界

所有回文半径中最靠右的位置。

初始:R在-1的位置;

0位置:只能扩到自己;

1位置:可以扩到2位置(#1#)

2位置:不行

3位置:可扩到6位置(#1#2#1#)

表示的是:每个位置下,R最右能到的位置。

3右边扩到了最右的0位置。

2.3 回文右边界的中心

C表示:第一次取得这个最右边界的中心位置。

0位置时,它的C是3.

3的右边界到它右边的1,后面的2的右边界也是2后面的1,但是1的C=3的位置(记录的是第一次到达的)。

3.分情况讨论

3.1 i位置不在回文右边界中——O(N)

比如刚开始的时候,R在-1位置,i在1位置。就是i不在回文右边界。

则暴力扩。

时间复杂度:R的变化范围是从0~N,所有扩的范围都在推后R,而且不会回退,所以总的时间复杂度是O(N)

3.2 i位置在回文右边界的里面

位置1的回文右边界在2位置,当i为2时,它在回文右边界的里面。

3.2.1 i'的回文半径在L里面——O(1)

由C和R得到回文左边界L,假设此时i的位置如图所示:

C肯定在i的左边。关于C做i的对称点i':

由回文数组中i'的回文半径,可得到一下多个可能性:

可能性1:i'的回文区域在L和C的中间

举例:

C:在F的位置

F的R和L在K位置

i'和i在b的位置

i'为重新的回文是aba,完全在L和C中间。

结论:i位置的回文半径和i'的相等

证明:

  1. 小R'到小L'之间肯定是回文结构
  2. 且这个范围不会扩的更大。

3.2.2 L和R没包住小L和小R——O(1)

举例:

此时i的回文半径就是i到R。

证明:

过程:

3.2.3 L压线

举例:

这种i的回文半径能不能扩的更大需要尝试。上例中,由于k=k,所以可以扩。

如下图,k≠s,不可以扩

时间复杂度同3.1:O(N)

4.应用

给定一个字符串,要求只能在串后面添加字符,使之成为一个回文串。要求添加的字符数最少。

比如,给定:

添加cba会使上串变为回文串,且最短。

它就是在求必须包含最后一个字符("1")的情况下,最长回文串是多少。前面不是的部分(“abc”)逆序过来,就是答案。

改写Manacher:

  • 一直求每个位置的回文半径。
  • 当R到达最后一个位置的时候,停。得到回文半径到R的位置C。此时有R和C。
  • 然后将R以C为中心,对称到R’。即得包含最后一个位置的最长回文串。
  • 然后将前面剩余部分逆序,添加到给定字符串的后面。

 

比如:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值