- 回文串问题
- 区间DP
class Solution:
### 0124 动态规划(228 ms,22.5 MB)
def countSubstrings(self, s: str) -> int:
n = len(s)
res = 0
dp = [[0] * n for _ in range(n)]
# 先选取回文串右边界
for r in range(n):
# 再选取回文串左边界
for l in range(r + 1):
# 前提条件:左右边界字符相等
# 后续条件:字符串长度小于2 or 之前的短字符串为回文串
if s[l] == s[r] and (r - l < 2 or dp[l+1][r-1]):
dp[l][r] = 1
res += 1
return res
### 0124 中心扩散法(136 ms,14.5 MB)
def countSubstrings(self, s: str) -> int:
# 中心扩散
def center(l, r):
while l >= 0 and r < n and s[l] == s[r]:
self.res += 1
l -= 1
r += 1
n = len(s)
self.res = 0
for l in range(n):
center(l, l) # 奇数长度回文串
center(l, l+1) # 偶数长度回文串
return self.res
516. 最长回文子序列
- 官方题解
- 动态规划
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
# dp[i][j] 表示字符串 s 的下标范围 [i,j] 内的最长回文子序列的长度
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
dp[i][i] = 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][n - 1]
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
f = [0] * n
for i in range(n - 1, -1, -1):
f[i] = 1
pre = 0 # f[i+1][i]
for j in range(i + 1, n):
tmp = f[j]
f[j] = pre + 2 if s[i] == s[j] else max(f[j], f[j - 1])
pre = tmp
return f[-1]