【算法题解】 最长公共子序列(力扣1143), 即LCS

1. 两个字符串的常用思路

用两个指针ij分别再字符串上移动

2. LCS分析:

str1和str2中必定有一个串的字符在LCS中,或者str1和str2都在LCS中

3. 解法:
法一:动态规划
  1. 明确dp数组含义:s1[0…i-1] 和 s2[0…j-1] 的lcs长度为dp[i][j],
	/*
	为什么要加1,原因是你可以不加1,
	但是不加1你就会用其它限制条件来确保这个index是有效的,
	而当你加1之后你就不需要去判断只是让索引为0的行和列表示空串。
	*/
	int[][] dp = new int[m+1][n+1];
  1. 代码
public int longestCommonSubsequence(String text1, String text2) {
    int m = text1.length();
    int n = text2.length();
    // dp定义:s1[0...i-1] 和s2[0...j-1]的lcs长度为dp[i][j]
    int[][] dp = new int[m + 1][n + 1];
    // 注意从1开始,m结束,因为i,j 为0时是空串,即dp table表中的第一行第一列全部为空
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            // 因为 i, j 现在是从1开始,所以下标开始是i-1
            if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
                //text1,和text2 都在LCS中,长度加一
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                // text1或text2 中至少有一个不再LCS中
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }

    }

    return dp[m][n];
}
法二:备忘录,去除重叠子问题
// 法二
int[][] memo;

public int longestCommonSubsequence(String text1, String text2) {
    int m = text1.length();
    int n = text2.length();
    memo = new int[m][n];
    for (int[] row : memo)
        Arrays.fill(row, -1);// 备忘录初始化为-1,

    return dp(text1, 0, text2, 0);// 从0开始,即空串开始查找,
}

public int dp(String str1, int i, String str2, int j) {

    // base case,空串返回0,
    if (str1.length() == i || str2.length() == j)
        return 0;

    // 如果之前已经算过了,那就返回,避免重复计算
    if (memo[i][j] != -1)
        return memo[i][j];

    // 找最长
    if (str1.charAt(i) == str2.charAt(j))// 都在lcs中,长度加一,str1,str2通知后移以为,因为最开始是从0开始的
        memo[i][j] =1 + dp(str1, i + 1, str2, j + 1);
    else // 至少有一个不在lcs中,str1和str2只有一个需要后移,且取最大的公共序列
        memo[i][j] = Math.max(dp(str1, i + 1, str2, j), dp(str1, i, str2, j + 1));

    return memo[i][j];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值