最近,我在接受采访时被问到以下问题。
给定字符串S,我需要找到另一个字符串S2,使得S2是S的子序列,并且S是S2 +反向的子序列(S2)。这里'+'表示连接。我需要为给定的S输出最小可能的S2长度。
我被告知这是一个动态编程问题但是我无法解决它。有人可以帮我解决这个问题吗?
编辑 -
有没有办法在O(N 2 )或更低的情况下执行此操作。
答案 0 :(得分:1)
这个问题有两个重要方面。
因此解决方案是从S的中心到S的末尾检查任何连续的元素。如果找到一个,则检查两侧的元素,如图所示。
现在,如果你能够到达字符串的末尾,那么元素的最小数量(结果)是从开始到找到连续元素的点的距离。在这个例子中它的C即3。
我们知道这可能永远不会发生。即你可能无法在中心找到连续的元素。让我们说连续元素在中心之后然后我们可以进行相同的测试。
主要字符串
子串
连接字符串
现在到了主要的疑点。为什么我们只考虑从中心开始的左侧?答案很简单,连接字符串由S + reverse(S)组成。所以我们确定子串中的最后一个元素在连接字符串中是连续的。主字符串的前半部分中的任何重复都无法产生更好的结果,因为至少我们应该在最终的连接字符串中有n个字母
现在复杂性问题: 搜索连续的字母表最多可以得到O(n) 现在迭代地检查任一侧的元素可以给出O(n)的最坏情况复杂度。即最大n / 2比较。 我们可能多次失败进行第二次检查,因此我们在复杂性之间存在乘法关系,即O(n * n)。
我认为这是一个正确的解决方案,但尚未找到任何漏洞。
答案 1 :(得分:0)
S中的每个角色都可以包含在S2中。有了它,我们可以构造递归,尝试两种情况:
并计算这两个封面的最小值。为了实现这一点,足以跟踪已经选择的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。