返回

让LeetCode5.最长回文子串为你拨开云雾见明月!

前端

大家好,欢迎来到我的技术博客。今天,我们将一起探讨LeetCode第5题,最长回文子串。

什么是回文子串?回文子串就是正反读都是一样的字符串。比如,“aba”是一个回文子串,因为无论从左到右读,还是从右到左读,都是一样的。

那么,如何找到一个字符串中最长的回文子串呢?这个问题看起来有点复杂,但其实有一个很简单的算法可以解决它。这个算法叫做“Manacher’s Algorithm”,又称“马拉车算法”。

Manacher’s Algorithm的基本思想是,先把字符串的每个字符之间都插入一个特殊字符“#”,然后把字符串两端也各插入一个特殊字符“#”。这样,字符串就变成了一个新的字符串,叫做“预处理字符串”。比如,字符串“aba”的预处理字符串就是“#a#b#a#”。

预处理字符串的好处是,它可以把所有回文子串都变成奇数长度的子串。这是因为,回文子串的中心字符两边的字符一定是相同的。而预处理字符串中,每个字符之间都插入了一个特殊字符“#”,所以回文子串的中心字符两边的字符一定是不同的。

我们把预处理字符串中的每个字符都看成一个点。那么,回文子串就对应着以某个点为中心的对称点序列。比如,字符串“aba”的预处理字符串“#a#b#a#”中,以点“b”为中心的对称点序列是“#a#b#a#”,这是一个回文子串。

现在,我们要做的就是找到预处理字符串中最长的回文子串。我们可以用动态规划来做。我们定义一个数组“p”,其中“p[i]”表示以点“i”为中心的最长回文子串的长度。

我们可以用下面的递推公式来计算“p[i]”:

p[i] = max(1, 2 * r - i - 1)

其中,

  • “r”是当前最长回文子串的右边界。
  • “i”是当前点的下标。

递推公式的意思是,以点“i”为中心的最长回文子串的长度要么是1,要么是当前最长回文子串的长度减去点“i”到当前最长回文子串的右边界之间的距离,再乘以2。

我们从左到右扫描预处理字符串,每次扫描一个点,都用递推公式计算出以该点为中心的最长回文子串的长度。扫描完所有点之后,我们就可以找到预处理字符串中最长的回文子串。

Manacher’s Algorithm的时间复杂度是O(n),其中“n”是字符串的长度。这是一个非常高效的算法,可以轻松地解决LeetCode第5题。

练习题

  1. 给定一个字符串,找到其中最长的回文子串。
  2. 给定一个字符串,找到其中所有回文子串。
  3. 给定一个字符串,找到其中最长的回文子序列。

如果您对LeetCode第5题或Manacher’s Algorithm还有任何疑问,欢迎在下方留言。我会尽快回复您的问题。