leetcode : 5. Longest Palindromic Substring
目录
0 参考文献
序号 | 标题 |
---|---|
1 | [LeetCode] Longest Palindromic Substring 最长回文子串 |
2 | 最长连续回文串(Longest Palindromic Substring) |
3 | 最长回文子串——Manacher 算法 |
4 | [Swift 算法] 马拉车算法 |
1 题目
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
2 解题方法
2.1 dp 动态规划
一个回文串例如 s=["b","a","b","a","d"] 其实有如下的特性:
- 对于s[ i+1 : j-1 ]的一个子串,必然也是回文串(比如以i=0 j=4 为例)
因此实际上我们可以得到如下的递推公式:
if s[ i+1 : j-1 ] is palindrome and s[i] == s[j] :
s[i:j] is palindrome
所以最后的解题方法其实就变成了用动态规划求解当前字符串的子字符串是否是回文串,同时当前字符的串的s[ i ] 和s [ j ]是否相等。
因此可以有如下的几个步骤:
2.1.1 创建和维护一个二维数组dp
如图所示,创建一个二维数组dp 。其中dp [ i ] [ j ] == True 则表示 字符串s[ i : j ]是回文串。初始化的时候,全部设置为False
2.1.2 处理单个字符的情况
对于一个字符,肯定是回文串。因此第一步先把上一步图中的矩阵的对角线都置为True
for i in range( 0 , l ):
dp[i][i] = True
ret = s[i:i+1]
2.1.3 处理单个字符的情况
接下来就是要处理2个字符串的情况:
# 2.1.3 处理2个字符串的情况
for i in range( 0, l-1 ):
if dp[i][i] == True and s[i] == s[i+1]:
dp[i][i+1] = True
2.1.4 处理3个以上的字符
对于3个以上的字符串,则就是从i=2开始到len - 2 结束对于每个字符串都检测一遍,是否所有的子串都是回文串,且s[ i ] == s [ j ]。最后dp中的结果如图:
2.1.5 最终代码
class Solution(object):
def longestPalindrome(self, s):
l = len(s)
dp = [[False for i in range(l)] for j in range(l)] # 2.1.1 创建和维护一个二维数组dp
ret = ""
ml = 0
# 2.1.2 处理单个字符的情况
for i in range( 0 , l ):
dp[i][i] = True
ret = s[i:i+1]
# 2.1.3 处理2个字符串的情况
for i in range( 0, l-1 ):
if dp[i][i] == True and s[i] == s[i+1]:
dp[i][i+1] = True
ret = s[i:i+2]
ml = 1
# 2.1.4 处理3个以上的字符
k = 2
while k < l :
for i in range( 0, l - k ):
j = i + k
if dp[i+1][j-1] == True and s[i] == s[j]:
dp[i][j] = True
if j - i > ml :
ret = s[i:j+1]
ml = j - i
k = k + 1
return ret
2.1.6 复杂度
很容易看出算法的时间复杂度是O(n^2)
2.2 [Manacher 算法] (马拉车算法)
doing
d