【LeetCode - 1143】最长公共子序列

本文介绍如何使用动态规划解决寻找两个字符串之间的最长公共子序列问题。通过详细解析状态转移方程,确定base_case,并逐步展示如何遍历计算得出最终结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述

在这里插入图片描述

2、解题思路

  本题只能穷举所有情况,然后对比所有的公共子序列,找出最长的那个,计算长度。

  因此,特别符合动态规划的条件,我们使用动态规划来求解。

  假设我们已经知道最长公共子序列,为 lcs。

  对两个字符串从右往左进行遍历检查字符属不属于 lcs:

  1、如果 text1.charAt(i) == text2.charAt(j),则此时两个字符肯定属于 lcs ,于是 dp[i][j] = dp[i-1][j-1] + 1,意思是现在知道了长度至少是 1 了,真正的长度得取决于两个字符串再往左的部分。

  2、如果 text1.charAt(i) != text2.charAt(j),则有三种情况:

  2.1 text1.charAt(i) 属于 lcs,text2.charAt(j) 不属于,则 dp[i][j] = d[i][j-1],即结果取决于 text2 的前 j-1 的情况;

  2.2 text1.charAt(i) 不属于 lcs,text2.charAt(j) 属于,则 dp[i][j] = d[i-1][j],即结果取决于 text1 的前 i-1 的情况;

  2.3 两个字符都不属于 lcs,则 dp[i][j] = dp[i-1][j-1]

  我们要找的是最长的公共子序列,于是选择上面三种情况最大的那个。

  于是,dp[i][j] = Max(d[i][j-1], d[i-1][j], dp[i-1][j-1])

  但是,对于两个字符都不属于的情况,会包含在 2.1 或 2.2 中,即 2.3 的值永远是最小的。

  可以简化为:dp[i][j] = Max(d[i][j-1], d[i-1][j])

  如果你不知道原理,也可以不简化,反正结果不变。

  知道了状态转移方程,接下来就是确定 base_case 和遍历计算。

  dp[i][0] == dp[0][j] == 0。即其中一个字符串长度为 0,则最长公共子序列不存在,长度为 0.

  最后返回 dp[word1.length][word2.length]

3、解题代码

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int len1 = text1.length();
        int len2 = text2.length();
        int[][] dp = new int[len1 + 1][len2 + 1];
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; 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]);
                }
            }
        }
        return dp[len1][len2];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值