最长回文子序列 问题是动态规划的重要应用之一。在实际生活中,很多信息都可以通过回文子序列来进行抽象和处理。本题旨在通过动态规划的方法,帮助我们有效地找到字符串中的最长回文子序列。
本文将详细阐述该问题的思路,包括如何定义状态、推导递推关系,并提供 Python 和 C++ 的实现代码,帮助读者更深入地理解动态规划的应用。

给定一个字符串
,求出该字符串的最长回文子序列的长度。回文子序列是指在字符串中删除一些字符(可以是零个或多个),使得剩下的字符能够组成一个回文字符串。
为子串
的最长回文子序列的长度。
,那
。
, 那
。
时,单个字符的最长回文子序列长度为 1 。
,其大小为
,其中
是字符串的长度。
1 ,表示每个单独字符的回文子序列长度为 1 。 数组,从长度 2 开始,直到
:计算毎一对 (i, j) 的回文子序列长度。
中,即整个字符串的最长回文子序列长度。
只依赖于
和
,可以将空间复杂度优化到
,只使用一维数组进行计算。
,可以处理长度适中的字符串。
数组的优化,可以大幅降低空间复杂度,使得算法在处理大规模输入时依然高效。
以上就是最长回文子序列问题的基本思路。
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
# 创建dp数组
dp = [[0] * n for _ in range(n)]
# 单个字符的回文子序列长度为1
for i in range(n):
dp[i][i] = 1
# 填充dp数组
for length in range(2, n + 1): # 子串长度从2到n
for i in range(n - length + 1):
j = i + length - 1 # 右边界
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]dp 并初始化每个单个字符的回文子序列长度为 1。dp[0][n-1],即整个字符串的最长回文子序列长度。class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
// 创建dp数组
vector<vector<int>> dp(n, vector<int>(n, 0));
// 单个字符的回文子序列长度为1
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
}
// 填充dp数组
for (int length = 2; length <= n; length++) { // 子串长度从2到n
for (int i = 0; i <= n - length; i++) {
int j = i + length - 1; // 右边界
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];
}
};dp 数组并设置每个单个字符的回文子序列长度为 1。dp 数组。dp[0][n-1],表示整个字符串的最长回文子序列的长度。