Skip to content

Latest commit

 

History

History
118 lines (95 loc) · 4.37 KB

README.md

File metadata and controls

118 lines (95 loc) · 4.37 KB

Given two strings str1 and str2, return the shortest string that has both str1 and str2 as subsequences.  If multiple answers exist, you may return any of them.

(A string S is a subsequence of string T if deleting some number of characters from T (possibly 0, and the characters are chosen anywhere from T) results in the string S.)

 

Example 1:

Input: str1 = "abac", str2 = "cab"
Output: "cabac"
Explanation: 
str1 = "abac" is a subsequence of "cabac" because we can delete the first "c".
str2 = "cab" is a subsequence of "cabac" because we can delete the last "ac".
The answer provided is the shortest such string that satisfies these properties.

 

Note:

  1. 1 <= str1.length, str2.length <= 1000
  2. str1 and str2 consist of lowercase English letters.

Related Topics:
Dynamic Programming

Similar Questions:

Solution 1. DP

Let dp[i][j] be the length of the shortest common supersequence of s[0..(i-1)] and t[0..(j-1)].

dp[i][j] = 1 + dp[i-1][j-1]                   if s[i-1] == t[j-1]
           1 + min(dp[i-1][j], dp[i][j-1])    if s[i-1] != t[j-1]
dp[0][i] = dp[i][0] = i

dp[M][N] is the length of the shortest common supersequence of s and t.

With this dp array, we can construct the shortest common supersequence.

// OJ: https://leetcode.com/problems/shortest-common-supersequence/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
class Solution {
public:
    string shortestCommonSupersequence(string s, string t) {
        int M = s.size(), N = t.size();
        vector<vector<int>> dp(M + 1, vector<int>(N + 1));
        for (int i = 1; i <= N; ++i) dp[0][i] = i;
        for (int i = 1; i <= M; ++i) dp[i][0] = i;
        for (int i = 1; i <= M; ++i) {
            for (int j = 1; j <= N; ++j) {
                if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        string ans(dp[M][N], ' ');
        for (int i = M, j = N, k = ans.size() - 1; k >= 0; --k) {
            if (i && j && s[i - 1] == t[j - 1]) ans[k] = s[--i], --j;
            else if (i && dp[i][j] == dp[i - 1][j] + 1) ans[k] = s[--i];
            else ans[k] = t[--j];
        }
        return ans;
    }
};

Solution 2. LCS

Let dp[i][j] be the length of longest common subsequence of s[0..(i-1)] and t[0..(j-1)].

dp[i][j] = 1 + dp[i-1][j-1]                   if s[i-1] == t[j-1]
           max(dp[i-1][j], dp[i][j-1])        if s[i-1] != t[j-1]
dp[0][i] = dp[i][0] = 0 

dp[M][N] is the length of the LCS of s and t, and M + N - dp[M][N] is the length of the shortest common supersequence.

We can use dp array to construct the shortest common supersequence as well.

// OJ: https://leetcode.com/problems/shortest-common-supersequence/
// Author: github.com/lzl124631x
// Time: O(MN)
// Space: O(MN)
// Ref: https://leetcode.com/problems/shortest-common-supersequence/discuss/312757/JavaPython-3-O(mn)-clean-DP-code-w-picture-comments-and-analysis.
class Solution {
public:
    string shortestCommonSupersequence(string s, string t) {
        int M = s.size(), N = t.size();
        vector<vector<int>> dp(M + 1, vector<int>(N + 1));
        for (int i = 1; i <= M; ++i) {
            for (int j = 1; j <= N; ++j) {
                if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        string ans(M + N - dp[M][N], ' ');
        for (int i = M, j = N, k = ans.size() - 1; k >= 0; --k) {
            if (i && j && s[i - 1] == t[j - 1]) ans[k] = s[--i], --j;
            else if (i && dp[i][j] == dp[i - 1][j]) ans[k] = s[--i];
            else ans[k] = t[--j];
        }
        return ans;
    }
};