问题描述
![](https://img-blog.csdnimg.cn/20191117153720811.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI3NjkwNzY1,size_16,color_FFFFFF,t_70)
解题报告
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示
s
s
s 的第
i
i
i 个字符到第
j
j
j 个字符组成的子串中,最长的回文序列长度是多少。所以:
i
f
s
[
i
]
=
=
s
[
j
]
⟶
d
p
[
i
]
[
j
]
=
d
p
[
i
+
1
]
[
j
−
1
]
+
2
i
f
s
[
i
]
≠
s
[
j
]
⟶
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
if \;s[i]==s[j] \longrightarrow dp[i][j]=dp[i+1][j-1]+2\\ if\; s[i]\neq s[j] \longrightarrow dp[i][j]=max(dp[i+1][j],dp[i][j-1])
ifs[i]==s[j]⟶dp[i][j]=dp[i+1][j−1]+2ifs[i]=s[j]⟶dp[i][j]=max(dp[i+1][j],dp[i][j−1])
在计算 d p [ i ] [ j ] dp[i][j] dp[i][j] 时,必须保证每个子问题都已经算好了。所以采用固定子序列的长度,依次确定子序列的起点的方式来确定一个子序列。
代码实现
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n=s.size();
vector<vector<int>>dp(n,vector<int>(n,0));
for(int i=0;i<n;i++){
dp[i][i]=1;
}
//d表示子序列的长度
for(int d=1;d<n;d++){
//i表示子序列的起点 i+d表示子序列的终点
for(int i=0;i+d<n;i++){
if(s[i]==s[i+d]){
dp[i][i+d]=dp[i+1][i+d-1]+2;
}
else{
dp[i][i+d]=max(dp[i+1][i+d],dp[i][i+d-1]);
}
}
}
return dp[0][n-1];
}
};