题目描述
解题思路
定义状态dp[i][j]
的含义为:s1从头到下标i的子字符串(s1[0…i]) 与 s1从头到下标j的子字符串(s2[0…j]) 的最长公共子序列的长度。
状态转移规律:
- 如果
s1[i]==s2[j]
:s1[0…i]和s2[0…j]的最长公共子序列 即为 在s1[0…i-1]和s2[0…j-1]的最长公共子序列后面分别加上字符s1[i]或s2[j],因此dp[i][j] = dp[i-1][j-1]+1
; - 如果
s1[i]!=s2[j]
,s1[0…i]和s2[0…j]的最长公共子序列 为下面两种情况中更长的一个:- s1[0…i-1]和s2[0…j]的最长公共子序列
- s1[0…i]和s2[0…j-1]的最长公共子序列
因此dp[i][j] = max{dp[i-1][j], dp[i][j-1]}
int solve(){
// init
// dp[0][0]
dp[0][0] = (s1[0]==s2[0]?1:0);
// dp[0][j]
for(int j=1; j<m; j++){
if(dp[0][j-1] == 1 || s2[j] == s1[0]){
dp[0][j] = 1;
}else{
dp[0][j] = 0;
}
}
// dp[i][0]
for(int i=1; i<n; i++){
if(dp[i-1][0] == 1 || s1[i] == s2[0]){
dp[i][0] = 1;
}else{
dp[i][0] = 0;
}
}
// bottom-up calc
for(int i=1; i<n; i++){
for(int j=1; j<m; j++){
if(s1[i] == s2[j]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[n-1][m-1];
}