当前位置:网站首页>LeetCode 1143. 最长公共子序列

LeetCode 1143. 最长公共子序列

2022-06-13 09:04:00 Shao_sen

1143. 最长公共子序列

难度 中等

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

  • 1 <= text1.length, text2.length <= 1000
  • text1text2 仅由小写英文字符组成。

题解

​ 这道题也是一道典型的dp题目,如果做过最长上升子序列等题目,对这道题理解和解题有帮助。先说一下什么是最长公共子序列(LCS:Longest Common Subsequence)吧。

​ 子序列和子串不一样,子串必须是连续的,子序列只需要保证前后顺序一样,但不保证连续。

​ 最长公共子序列是指,两个字符串中,能不能找出其中最长连续或不连续的子序列,如果我们没有了解动态规划做法,其实也可以暴力破解,就是把两个字符串的所有子序列找出来,如果t1长度为n,t2长度为m,那t1的子序列就有2n个,t2的子序列就有2m个,时间复杂度高达2^(n+m)。

​ 那肯定不能考虑暴力破解,那动态规划是怎么解题的。

​ 我们得借助二维的辅助数组来记录最长公共子序列的长度,dp[i] [j]记录的是长度为 i 和长度为 j 的字符串的最长公共子序列长度。有了辅助数组,那我们需要根据状态找到动态规划转移方程。

  • 如果一个字符串长度为0的空串,那另外一个串长度为多少都不可能有公共子序列,即dp[i] [0] = dp[0] [j] = 0

  • 如果t1[i] = t2[j],那么dp[i] [j] = dp[i - 1] [j - 1] + 1,因为dp[i - 1] [j - 1]记录的是t1[0: i - 1] 和t2[0: j - 1] 的最长公共子序列长度,如果t1[i] = t2[j]的话,那长度加一。

    ​ 例如acef和def,当变量到ace和de是,最长公共子序列长度为1,只有最后的e相同,然后加入f之后,最长公共子序列长度为2,即1(dp[i - 1] [j -1]) + 1

  • 如果t1[i] ≠ t2[j],dp[i] [j]应等于什么呢。我们应该想一下dp[i] [j]表示的是什么,dp[i] [j]表示是t1[0: i] 和t2[0: j] 的最长公共子序列长度,那我们应该取dp[i] [j - 1]和dp[i - 1] [j]其中最大一项。

    ​ 为啥是取这两者最大一项,因为dp[i] [j - 1]代表t1[i]和t2[j-1],dp[i - 1] [j]代表t1[i-1]和t2[j],这两种状态包含了t1[i] ≠ t2[j]时的所有可能的最长公共子序列。

class Solution {
    
    public int longestCommonSubsequence(String text1, String text2) {
    
        int len1 = text1.length();//长度1
        int len2 = text2.length();//长度2
        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)){
    //t1[i] = t2[j],那么dp[i] [j] = dp[i - 1] [j - 1] + 1
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }else{
    //t1[i] ≠ t2[j],那么取dp[i] [j - 1]和dp[i - 1] [j]其中最大一项
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[len1][len2];
    }
}
原网站

版权声明
本文为[Shao_sen]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Shaosenmonitor/article/details/124945153