【数据结构与算法】Manacher算法

Manacher算法是一种在O(N)时间内求解字符串最长回文子串的算法,通过巧妙处理回文串的奇偶性和对称性,避免了O(N^3)的时间复杂度。该算法涉及到回文半径、最右回文边界和回文直径等概念,并通过动态扩展找到最长回文子串。文章还解释了如何利用该算法解决最少添加字符变成回文串的问题。
摘要由CSDN通过智能技术生成

Manacher算法

https://github.com/SongJianHIT/DataStructurs-Algorithm/tree/main/src/algorithms/manacher

基本介绍

Manacher 算法常用于 求一个字符串中的最长回文子串。如:abc123321def 的最长回文子串为 123321

计算字符串的最长回文字串最简单的算法就是枚举该字符串的每一个子串,并且判断这个子串是否为回文串,这个算法的时间复杂度为 O ( N 3 ) O(N^3) O(N3) 的。Manacher 算法可以在 线性时间复杂度 O ( N ) O(N) O(N) 内求出一个字符串的最长回文字串,达到了理论上的下界。

Manacher 算法原理与实现

首先,Manacher 算法提供了一种巧妙的办法,将长度为奇数的回文串和长度为偶数的回文串一起考虑,具体做法是,在原字符串的每个相邻两个字符中间插入一个分隔符,同时在首尾也要添加一个分隔符,分隔符的要求是不在原串中出现,一般情况下可以用 # 号。如:

image-20230105112016065

概念:回文直径与回文半径

举个例子,如字符串 abc12321def 的回文子串为 12321,因此回文直径为 5,回文半径为 3;又如字符串 1221,回文直径为 4,回文半径为 2。

概念:回文半径数组 pArr

原始串再添加了特殊字符 # 后,得到处理串。

我们在处理串上,对每个字符 T[i],记录以 T[i] 为中心的最长回文字串的最右字符到 T[i] 的长度**(回文半径)**。比如以 T[i] 为中心的最长回文字串是 T[l,r],那么 Len[i]=r-i+1

概念:最右回文边界 R

最右回文边界是一个 int 类型整数。初始值 int R = -1;。他的含义是,不管是从哪个位置 i 作为中心点向左右两边扩,只要扩出来的回文区域的右边界更靠右了,就更新 R

概念:取得最右回文右边界的中心 C

取得最右回文右边界的中心是一个 int 类型整数。初始值 int C = -1;R 只要更新,C 就负责记录是哪个中心点扩的时候让 R 更新了。

对上述概念举个例子:

IMG_42D84C15A973-1

算法流程

Manacher 算法从 index=0 开始,以 str'[index] 为中心,向左右两边扩,找最长回文子串。

index=i 时,有如下几种情况:

  1. i 没有被 R 扩住,即 i > R

    此时,无法优化,暴力扩就行了。

  2. iR 扩住,即 i <= R

    此时存在这种拓扑关系 [L i' C i R]i'i 关于 C 的对称点。比较特殊的是 iR 重叠,但讨论一样。

    接下来,分类讨论:

    • 情况 1i' 扩出来的区域彻底在 [L, R]

      IMG_EDD6997AF5DB-1

      此时,i 不用扩了,i 的回文区域大小与 i' 一样大。

    • 情况 2i' 扩出来的区域跑到 [L, R] 外面了

      IMG_723D1305D386-1

      此时,i 不用扩了,i 的回文区域只会到 R,回文半径可计算为 R - i + 1

    • 情况 3i' 的左边界与回文区域重合

      IMG_2FB5E0AEEEEC-1

      此时,i 的回文区域至少是 i' 那么大,但还有可能更大!

经典题目

题目一:最少添加多少字符变成回文串

在一个字符串中,只能够在字符串的后面添加字符,最少需要添加多少个字符,使其能够变成回文串。

如:str=[abc12321],要使其变成回文串,最少需要 3 个字符 [cba]

解决方法

这道题实际上是在求,必须包括最后一个字符的情况下,最长回文子串是多长,长度记为 x。字符串总长度为 len,要使其变为回文串,则最少需要 len - x 个字符即可。

只要找到 必须包括最后一个字符的情况下,最长回文子串是多长 后,把前面的字符串逆序即可。

怎么找呢?

  • 每个 index 都推出一个右边界,当右边界到达最后一个字符串时,停!就找到此时的中心 C,这就是最长回文串的中心。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

见见大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值