通过遍历每个回文中心,向两边扩散,并判断是否回文字串。在遍历中心点的时候,要注意中心点有两种情况。一个元素可以作为中心点,两个元素也可以作为中心点。
dp
class Solution:
def countSubstrings(self, s: str) -> int:
dp = [[False] * len(s) for _ in range(len(s))]
res = 0
for i in range(len(s) - 1, -1, -1):
for j in range(i, len(s)):
if s[i] == s[j]:
if j - i <= 1: # 情况1 和 情况2
dp[i][j] = True
res += 1
elif dp[i + 1][j - 1]: # 情况3
dp[i][j] = True
res += 1
return res
O(n^2)
O(n^2)
双指针
class Solution:
def countSubstrings(self, s: str) -> int:
res = 0
for i in range(len(s)):
l, r = i, i
# odd case
while l >= 0 and r < len(s) and s[l] == s[r]:
res += 1
l -= 1
r += 1
# even case
l, r = i, i+1
while l >= 0 and r < len(s) and s[r] == s[l]:
res += 1
l -= 1
r += 1
return res
O(n^2)
O(1)
dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。
递推公式:
dp[i][j] = dp[i + 1][j - 1] + 2
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
初始化:其他为0,dp[i][i] = 1
遍历顺序:从下到上,从左到右
举例推导:输入s:“cbbd” 为例,dp数组状态如图:
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
dp = [[0] * len(s) for _ in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for i in range(len(s) - 1, -1, -1):
for j in range(i + 1, len(s)):
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]
O(n^2)
O(n^2)