package LeetCode_1092 import java.lang.StringBuilder /** * 1092. Shortest Common Supersequence * https://leetcode.com/problems/shortest-common-supersequence/description/ * * 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 <= str1.length, str2.length <= 1000 str1 and str2 consist of lowercase English letters. * */ class Solution { /* * solution:dp, Time complexity:O(mn), Space complexity:O(mn) * 1.find the longest common sub sequence of two string * 2.insert non-lcs characters to the lcs find below * */ fun shortestCommonSupersequence(str1: String, str2: String): String { val resSb = StringBuilder() val dp = getLcsDP(str1, str2) var i = str1.length var j = str2.length val commonSb = StringBuilder() while (dp[i][j] != 0) { if (dp[i][j] == dp[i - 1][j]) { i-- } else if (dp[i][j] == dp[i][j - 1]) { j-- } else { commonSb.append(str1[i - 1]) i-- j-- } } val newString = commonSb.toString().reversed() val newLen = newString.length val len1 = str1.length val len2 = str2.length i = 0 j = 0 for (k in 0 until newLen) { while (i < len1 && str1[i] != newString[k]) { resSb.append(str1[i++]) } while (j < len2 && str2[j] != newString[k]) { resSb.append(str2[j++]) } resSb.append(newString[k]) i++ j++ } while (i < len1) { resSb.append(str1[i++]) } while (j < len2) { resSb.append(str2[j++]) } return resSb.toString() } private fun getLcsDP(str1: String, str2: String): Array<IntArray> { val m = str1.length val n = str2.length val dp = Array(m + 1) { IntArray(n + 1) } for (i in 1..m) { for (j in 1..n) { if (str1[i - 1] == str2[j - 1]) { dp[i][j] = 1 + dp[i - 1][j - 1] } else { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) } } } return dp } }