Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeetCode 1143. Longest Common Subsequence #21

Open
Woodyiiiiiii opened this issue Apr 21, 2020 · 0 comments
Open

LeetCode 1143. Longest Common Subsequence #21

Woodyiiiiiii opened this issue Apr 21, 2020 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Apr 21, 2020

Given two strings text1 and text2, return the length of their longest common subsequence.

A subsequence of a string is a new string generated from the original string with some characters(can be none) deleted without changing the relative order of the remaining characters. (eg, "ace" is a subsequence of "abcde" while "aec" is not). A common subsequence of two strings is a subsequence that is common to both strings.

If there is no common subsequence, return 0.

Example 1:

Input: text1 = "abcde", text2 = "ace" 
Output: 3  
Explanation: The longest common subsequence is "ace" and its length is 3.

Example 2:

Input: text1 = "abc", text2 = "abc"
Output: 3
Explanation: The longest common subsequence is "abc" and its length is 3.

Example 3:

Input: text1 = "abc", text2 = "def"
Output: 0
Explanation: There is no such common subsequence, so the result is 0.

Constraints:

  • 1 <= text1.length <= 1000
  • 1 <= text2.length <= 1000
  • The input strings consist of lowercase English characters only.

仍是用线性DP的思路去做。创建一个二维dp数组,dp[i][j]代表第一个字符串的前 i个字符和第二个字符串的前 j个字符的最长公共子序列长度(从下标1开始)。
初始时:dp[i][0] = dp[0][j] = 0,表示空串和任何非空串都没有公共子序列。
状态转移方式:如果当前第一个字符串的第i个字符和第二个字符串的第j个字符相等,那么

1. dp[i][j] = dp[i - 1][j - 1] + 1
2. dp[i][j] = Math.max(dp[i - 1][j - 1] + 1, Math.max(dp[i - 1][j], dp[i][j - 1]))

否则

dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])

返回dp[m][n]。

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int m = text1.length(), n = text2.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
                    // 1.dp[i][j] = dp[i - 1][j - 1] + 1;
                    // 2.
                    dp[i][j] = Math.max(dp[i - 1][j - 1] + 1, 
                                        Math.max(dp[i - 1][j], dp[i][j - 1]));
                }
                else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        
        return dp[m][n];
    }
}

总结:
首先这是动态规划中的Min/Max paths问题,创建二维数组,设置大小((m + 1) * (n + 1)),这样就不用考虑边界问题,如果是(m* n)那么要初始化第一行第一列。确定dp[i][j]的含义——第一个字符串的前 i个字符和第二个字符串的前 j个字符的最长公共子序列长度。每个位置代表一种状态,接下来确定状态转移函数,dp[i][j]由其左边,上边和左上边的位置决定。当字符串1的第i个字符与字符串2的第j个字符不相等的话,可以忽视text1[i]或者text2[j]的状态,从左边和上边选择最大的子序列长度;反之如果字符相等,那么要从左上角的最大公共序列长度取出再加一。可以举一个例子,比如字符串1是abcd,另一个是aec,当i = j = 2时,其dp数值等于第1个索引也是第0个索引的值加一。
因为有m * n个状态,所以空间复杂度为O(m * n),时间复杂度为O(m * n)。


参考资料:

  1. LeetCode原题
  2. https://www.acwing.com/solution/LeetCode/content/3432/
  3. https://blog.csdn.net/DaVinciL/article/details/99545037
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant