动规最长回文子序列模板
状态设计
dp[i][j] : s[i~j]中最长的回文子序列的长度
状态转移
s[i] == s[j]
dp[i][j] = dp[i+1][j-1] + 2
两头相同 中间的最长的回文子序列+2(就是两头的)
s[i] != s[j]
dp[i][j] = max(dp[i+1][j], dp[i][j-1])
两头不同 先去掉头试试 再去掉尾试试
初始化
dp[i][i] = 1
递推顺序
小区间 -> 大区间
答案
dp[0][n-1](如果不知道为什么 那么再读一读本章 ⌈状态设计⌋ 再想想dp[0][n-1]是什么意思)
代码
/*
dp[i][j] : s[i~j]中最长的回文子序列的长度
转移
s[i] == s[j] dp[i][j] = dp[i+1][j-1] + 2
s[i] != s[j] dp[i][j] = max(dp[i+1][j], dp[i][j-1])
初始化
地推顺序
答案
*/
const int N = 1005;
int dp[N][N];
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
if (n == 1)
return 1;
for (int i = 0; i < n; i ++)
dp[i][i] = 1;
for (int len = 2; len <= n; len ++) {
for (int i = 0; i + len - 1 < n; i ++) {
int j = i + len - 1;
if (s[i] == s[j])
dp[i][j] = dp[i + 1][j - 1] + 2;
if (s[i] != s[j])
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
return dp[0][n - 1];
}
};