动态规划
思路:
- 初始化
- 定义状态:定义一个二维数组 dp,其中 dp[i][j] 表示字符串 text1 的前 i 个字符和字符串 text2 的前 j 个字符的最长公共子序列的长度。
- 初始化边界条件:dp[0][j] 和 dp[i][0] 都初始化为 0,因为当其中一个字符串为空时,它们的公共子序列长度为 0。
- 状态转移
遍历字符串:使用两个嵌套的循环,分别遍历 text1 和 text2 的所有字符。外层循环遍历 text1 的每个字符,内层循环遍历 text2 的每个字符。
状态转移方程:对于每一对字符 text1[i-1] 和 text2[j-1](注意,由于 dp 的索引比字符串索引多 1,因此这里使用 i-1 和 j-1):- 如果
text1[i-1] == text2[j-1]
,则找到了一个公共字符,更新dp[i][j] 为 dp[i-1][j-1] + 1
。 - 如果
text1[i-1] != text2[j-1]
,则当前字符不可能是公共子序列的一部分,更新dp[i][j] 为 dp[i-1][j] 和 dp[i][j-1] 中的较大值
。
- 如果
- 计算结果
- 记录最大长度:在状态转移的过程中,更新一个变量 res,用于记录 dp 数组中的最大值,即两个字符串的最长公共子序列的长度。
- 返回结果:当遍历完所有字符后,res 即为所求的最长公共子序列的长度。
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int res = 0;
int[][] dp = new int[text1.length() + 1][text2.length() + 1];
for(int i = 1; i < text1.length() + 1; i++){
for(int j = 1; j < text2.length() + 1; j++){
if(text1.charAt(i - 1) == text2.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
res = Math.max(res, dp[i][j]);
}
}
return res;
}
}