【问题标题】:Minimum number of subsequences required to interleave one string to another将一个字符串交错到另一个字符串所需的最小子序列数
【发布时间】:2021-10-02 11:37:51
【问题描述】:

我看到了原题Minimum of subsequences required to convert one string to another,和LeetCode上的这个问题1055. Shortest Way to Form String很相似。

说明:

给定两个字符串 source 和 target,返回 source 的最小子序列数,使得它们的 串联 等于 target。如果任务不可能完成,返回-1。

示例 1:

输入:源 = "abc",目标 = "abcbc"

输出:2

说明:目标“abcbc”可以由“abc”和“bc”组成,它们是源“abc”的子序列。

假设s'source的子序列,所以这个问题就是找到s'_1s'_2...s'_k形成target。我的问题是如何找到将一个字符串交错到另一个字符串所需的最小子序列数。

例如:

输入:source = "adbsc", target = "addsbc"

输出:2

解释:

step1: s'1 = adbc, then target' = ds
step2: s'2 = ds, then target' = ""

不知道能不能解决这个问题,把sourcetarget'的最长公共子序列去掉,形成t',重复直到t' = ""

这是我的代码:

class Solution:
    def shortestWay(self, s: str, t: str) -> int:

        def lcs(s: str, t: str) -> str:
            m, n = len(s), len(t)
            dp = [[0] * (n + 1) for _ in range(m + 1)]
            for i in range(1, m + 1):
                for j in range(1, n + 1):
                    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])
            choose = [False] * n
            i, j = m, n
            while i + j != 0:
                if s[i-1] == t[j-1]:
                    choose[j-1] = True
                    i, j = i - 1, j - 1
                elif dp[i][j] == dp[i-1][j]:
                    i -= 1
                elif dp[i][j] == dp[i][j-1]:
                    j -= 1
            print(f'lcs({s}, {t}) is', ''.join(t[i] for i, v in enumerate(choose) if v))
            return ''.join(t[i] for i, v in enumerate(choose) if not v)
        ans = 0
        while t:
            ans += 1
            t1 = lcs(s, t)
            print(repr(t1))
            if t1 == t:
                return -1
            t = t1
        return ans
"""
lcs(adbsc, addsbc) is adbc
'ds'
lcs(adbsc, ds) is ds
''
"""

有人可以帮我证明/解决这个问题吗,谢谢!

【问题讨论】:

    标签: string algorithm subsequence


    【解决方案1】:

    您为第二个示例(source = “abc”,target = “abcbc”)所做的工作对我来说没有意义。您的算法想法(反复从目标中移除 LCS)会产生最佳解决方案——您只需要证明没有其他解决方案可以更好。

    校样草图

    考虑一个包含 OPT 段的最佳解决方案。如果它等于您的算法的解决方案,那么我们就完成了;否则,它必须由一定数量的公共子序列段组成,其中前 k 个(可能 k=0)与您的算法生成的段匹配,然后是严格短于算法的第(k+1)个段(k+1)-th 段(因为您的算法总是选择在每个阶段添加的可能最长的段),然后是一些(可能为零)剩余段。

    请注意,如果字符串 S 的某个子序列等于字符串 T,那么对于任何给定的 T 的后缀,我们当然可以找到一个等于它的 S 子序列——我们只需要要做的是从子序列中删除一些初始字符。

    所以,回到我们最初的问题:剩余段的一些初始部分(可能涉及多个段)可以被修剪掉以产生一个段列表,当附加到您的算法产生的前 k+1 个段时, 给出了一个解决方案:

    • 同意算法解决方案的前 k+1 段,并且
    • 段数不低于 OPT。

    我们开始的最优解与你的算法在前 k 段上的解一致;这一新的最优解决方案至少在一个细分市场上达成一致。如果新解决方案尚未完全等于您的算法的解决方案,则可以重复分析,生成至少在前 k+2 段上与其一致的新解决方案。这可以重复,直到我们最终产生一个与您的算法解决方案完全一致并且具有长度 OPT 的解决方案。由于我们没有对输入实例做任何假设,这证明您的算法对每个输入实例都产生了最优解。

    【讨论】:

      猜你喜欢
      • 2020-08-10
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 2013-08-19
      • 2020-04-13
      • 1970-01-01
      • 2021-09-26
      相关资源
      最近更新 更多