回文子串是要连续的,回文子序列可以不是连续的! 回文子串、回文子序列都是动态规划经典题目。
回文子串
class Solution:
def countSubstrings(self, s: str) -> int:
if not s: return 0
n = len(s)
dp = [[False] * n for _ in range(n)]
res = 0
for i in range(n - 1, -1, -1):
for j in range(i, n):
if s[i] == s[j] and (j - i < 2 or dp[i + 1][j - 1]):
res += 1
dp[i][j] = True
return res
最长回文子串
该题与上一题类似,只是记录最长的那一个回文子串,代码整体一致。
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)]
out_s = temp = str()
for i in range(n - 1, -1, -1):
for j in range(i, n):
if s[i] == s[j] and (j - i <= 1 or dp[i + 1][j - 1]):
dp[i][j] = True
temp = s[i:j + 1]
if len(temp) >= len(out_s): out_s = temp
else:
temp = str()
return out_s
以上两题也可以采用中心扩展法,具体讲解参照两道回文子串的解法(详解中心扩展法)
# 回文子串
class Solution:
def countSubstrings(self, s: str) -> int:
if not s: return 0
n = len(s)
res = 0
for i in range(2 * n - 1):
l = i // 2
r = l + i % 2
while l >= 0 and r < n and s[l] == s[r]:
res += 1
l -= 1
r += 1
return res
# 最长回文子串
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
out_s = temp = str()
for i in range(2 * n - 1):
l = i // 2
r = l + i % 2
while l >= 0 and r < n and s[l] == s[r]:
temp = s[l : r + 1]
l -= 1
r += 1
if len(temp) >= len(out_s): out_s = temp
return out_s
# 也可以写成以下形式:
class Solution:
def countSubstrings(self, s: str) -> int:
n = len(s)
res = 0
for i in range(n):
res += self.funer(s, i, i, 0)
res += self.funer(s, i, i + 1, 0)
return res
def funer(self, s, i, j, res):
while i >= 0 and j < len(s) and s[i] == s[j]:
i -= 1;j += 1;res += 1
return res
class Solution:
def longestPalindrome(self, s):
res = ""
for i in range(len(s)):
# odd case, like "aba"
tmp = self.helper(s, i, i)
if len(tmp) > len(res):
res = tmp
# even case, like "abba"
tmp = self.helper(s, i, i+1)
if len(tmp) > len(res):
res = tmp
return res
# get the longest palindrome, l, r are the middle indexes
# from inner to outer
def helper(self, s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1; r += 1
return s[l+1:r]
最长回文子序列
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
for i in range(n - 1, -1, -1):
for j in range(i + 1, n):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][-1]