Post

1170 Shortest Common Supersequence

1170 Shortest Common Supersequence

Shortest Common Supersequence image

Given two strings str1 and str2, return the shortest string that has both *str1 and str2 as subsequences*. If there are multiple valid strings, return any of them.

A string s is a subsequence of string t if deleting some number of characters from t (possibly 0) results in the string s.

 

Example 1:

1
2
3
4
5
6
7
8
**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.

Example 2:

1
2
3
4
**Input:** str1 = "aaaaaaaa", str2 = "aaaaaaaa"
**Output:** "aaaaaaaa"

 

Constraints:

1
2
1 <= str1.length, str2.length <= 1000
str1 and str2 consist of lowercase English letters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

class Solution:
    def shortestCommonSupersequence(self, str1: str, str2: str) -> str:
        # it is possible that s1 is sub sequence of s2 
        # then s2 is ans
        # a sub string of s1 is subsequence of s2
        # then shortest would be s1`+common+s2`
        # how to check if something s a subseq -> 
        # T[i,j] = T[i-1,j-1] if a[i] == a[j]
        #        = False
        # in the arr find the longest True or 1 occurence
        # and attach the remaining chars at start or end, many ans possible
        m, n = len(str1), len(str2)

        # Step 1: Compute LCS table
        T = [[0] * (n + 1) for _ in range(m + 1)]
        
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if str1[i - 1] == str2[j - 1]:
                    T[i][j] = 1 + T[i - 1][j - 1]
                else:
                    T[i][j] = max(T[i - 1][j], T[i][j - 1])
        
        # Step 2: Backtrack to get LCS
        i, j = m, n
        lcs = []
        # this is very imp as I got this incorrect , LCS needs back tracking 
        # a simple max_len - adoes not work
        while i > 0 and j > 0:
            if str1[i - 1] == str2[j - 1]:
                lcs.append(str1[i - 1])
                i -= 1
                j -= 1
            elif T[i - 1][j] >= T[i][j - 1]:
                i -= 1
            else:
                j -= 1
        
        lcs.reverse()
        lcs = ''.join(lcs)

        # Step 3: Construct SCS using LCS as anchor
        i, j = 0, 0
        scs = []

        for c in lcs:
            while i < len(str1) and str1[i] != c:
                scs.append(str1[i])
                i += 1
            while j < len(str2) and str2[j] != c:
                scs.append(str2[j])
                j += 1
            scs.append(c)
            i += 1
            j += 1

        scs.append(str1[i:])
        scs.append(str2[j:])

        return ''.join(scs)





This post is licensed under CC BY 4.0 by the author.