要删除的最小子字符串的长度

时间:2018-03-29 19:19:45

标签: string algorithm

假设我们有两个字符串,我们称之为s1s2。现在,我们要从s2中删除这样的子字符串,s2将是s1后面的子序列,并且删除的字符串的长度最小。

例如,对于s1 = "abbcabaa"s2 = "accbccbaa",此类字符串为cbcc - 从s2删除后,我们会留下acbaa,这是一个s1的后续序列。它的长度4是最小的。

另一个例子 - s1 = "abcaacb"s2 = "adacaa"。这样的字符串是"da" - 我们在删除后留下acaa,这是abcaacb的子序列。它的长度2很小。

任何解决问题的想法

1 个答案:

答案 0 :(得分:1)

这可以在O(n + m)中求解,其中n是一个字符串的长度,m是另一个字符串的长度。

你可以通过在s1的第一个字符和s2的第一个字符上指定一个指针来实现。现在如果字符是相同的,则将两个指针向前移动,否则仅指向s1的指针。这将生成最终删除最短子串的最佳结果。现在反过来重复相同的过程。

s1:                           abbcabaa
match s2 from beginning:      a  c    cbccaa
match s2 from the end:   accbc   c baa

每次角色匹配时,您都会保存索引。在这里,我们将有以下两个列表:

from beginning (a): [[0, 0], [1, 3]]
from the end   (b): [[8, 7], [7, 6], [6, 5], [5, 3]]

现在,您可以再次使用两个指针计算删除字符串中间子字符串的最佳结果。从a中的第一个元素和b中的最后一个元素开始,在a中逐步向前移动,然后在b中向后移动,直到b中s1的索引大于a中的s1。在每个步骤计算必须删除的子串的长度。并跟踪最低限度。

第1步:pa = [0,0],pb = [5,3],因此必须删除索引1到4(包括)的子串(ccbc)

第二步:pa = [1,3],pb = [6,5],必须删除索引2到5的子串(cbcc)

最后我们可以看到有两个长度为4的最佳解决方案:ccbc和cbcc。

在这里,同样的事情转化为代码:



// returns [startIndex (inclusive), endIndex (exclusive)]
function minSubstr(s1, s2) {
    let p2 = 0, a = [], b = []
    for (let p1 = 0; p1 < s1.length; p1++)
        if (s1[p1] == s2[p2]) {
            if (p2 + 1 == s2.length)
                return [0, 0] // no removal needed, s2 is subsequence of s1
            a.push([p1, p2++])
        }
    let best = [p2, s2.length]
    p2 = s2.length - 1
    for (let p1 = s1.length - 1; p1 >= 0; p1--)
        if (s1[p1] == s2[p2])
            b.push([p1, p2--])
    if (best[1] - best[0] > p2 + 1)
        best = [0, p2 + 1]
    let pb = b.length - 1
    for (let pa = 0; pa < a.length; pa++) {
        while (pb >= 0 && b[pb][0] <= a[pa][0])
            pb--
        if (pb < 0)
            break
        if (b[pb][1] - a[pa][1] - 1 < best[1] - best[0])
            best = [a[pa][1] + 1, b[pb][1]]
    }
    return best
}

let s1 = "abbcabaa", s2 = "accbccbaa"
console.log("s1 = " + s1); console.log("s2 = " + s2)
let best = minSubstr(s1, s2)
console.log("best = " + best + " (" + s2.substring(best[0], best[1]) + ")")
s1 = "abcaacb"; s2 = "adacaa"
console.log("s1 = " + s1); console.log("s2 = " + s2)
best = minSubstr(s1, s2)
console.log("best = " + best + " (" + s2.substring(best[0], best[1]) + ")")
&#13;
&#13;
&#13;