搜索符合某些条件的最小字符串

时间:2016-04-27 19:10:27

标签: string dynamic-programming subsequence

最近,我在接受采访时被问到以下问题。

给定字符串S,我需要找到另一个字符串S2,使得S2是S的子序列,并且S是S2 +反向的子序列(S2)。这里'+'表示连接。我需要为给定的S输出最小可能的S2长度。

我被告知这是一个动态编程问题但是我无法解决它。有人可以帮我解决这个问题吗?

编辑 -

有没有办法在O(N 2 )或更低的情况下执行此操作。

3 个答案:

答案 0 :(得分:1)

这个问题有两个重要方面。

  1. 由于我们需要S作为S2 +反向(S2)的子串,所以S2应该有 至少n / 2长度。
  2. 在S2和反向(S2)的连接之后,存在一种模式 字母表重复,如
  3. enter image description here

    因此解决方案是从S的中心到S的末尾检查任何连续的元素。如果找到一个,则检查两侧的元素,如图所示。

    enter image description here

    现在,如果你能够到达字符串的末尾,那么元素的最小数量(结果)是从开始到找到连续元素的点的距离。在这个例子中它的C即3。

    我们知道这可能永远不会发生。即你可能无法在中心找到连续的元素。让我们说连续元素在中心之后然后我们可以进行相同的测试。

    主要字符串

    enter image description here

    子串

    enter image description here

    连接字符串

    enter image description here

    现在到了主要的疑点。为什么我们只考虑从中心开始的左侧?答案很简单,连接字符串由S + reverse(S)组成。所以我们确定子串中的最后一个元素在连接字符串中是连续的。主字符串的前半部分中的任何重复都无法产生更好的结果,因为至少我们应该在最终的连接字符串中有n个字母

    现在复杂性问题: 搜索连续的字母表最多可以得到O(n) 现在迭代地检查任一侧的元素可以给出O(n)的最坏情况复杂度。即最大n / 2比较。 我们可能多次失败进行第二次检查,因此我们在复杂性之间存在乘法关系,即O(n * n)。

    我认为这是一个正确的解决方案,但尚未找到任何漏洞。

答案 1 :(得分:0)

S中的每个角色都可以包含在S2中。有了它,我们可以构造递归,尝试两种情况:

  • S的第一个字符用于封面,
  • S的第一个字符不是 用于封面,

并计算这两个封面的最小值。为了实现这一点,足以跟踪已经选择的S2 +反向(S2)覆盖了多少S。

我们知道结果是什么(找到封面,不能有封面)有优化,如果它不能覆盖某些内容,则不需要将第一个字符作为封面。

简单的python实现:

cache = {}

def S2(S, to_cover):
    if not to_cover:  # Covered
        return ''
    if not S:         # Not covered
        return None
    if len(to_cover) > 2*len(S):  # Can't cover
        return None
    key = (S, to_cover)
    if key not in cache:
        without_char = S2(S[1:], to_cover)     # Calculate with first character skipped
        cache[key] = without_char
        _f = to_cover[0] == S[0]
        _l = to_cover[-1] == S[0]
        if _f or _l:
            # Calculate with first character used
            with_char = S2(S[1:], to_cover[int(_f):len(to_cover)-int(_l)])
            if with_char is not None:
                with_char = S[0] + with_char  # Append char to result
                if without_char is None or len(with_char) <= len(without_char):
                    cache[key] = with_char
    return cache[key]

s = '21211233123123213213131212122111312113221122132121221212321212112121321212121132'
c = S2(s, s)
print len(s), s
print len(c), c

答案 2 :(得分:0)

让我们说S2是&#34; apple&#34;。然后我们可以做出这样的假设:

S2 + reverseS2 &gt; = S &gt; = S2
&#34; appleelppa&#34; &gt; = S &gt; = &#34; apple&#34;

所以给定的S会包括&#34; apple&#34;不超过&#34; appleelp&#34;。它可能是&#34; appleel&#34;或&#34; appleelpp&#34;。

& x.weekday==1

恭喜,您找到了最低S2。