最近在面试中,我被问到了下面这个问题。
给定一个字符串S,我需要找到另一个字符串S2,使得S2是S的一个子序列,并且S也是S2+reverse(S2)的一个子序列。这里的“+”表示字符串连接。我需要输出给定S情况下S2的最小长度。
我被告知这是一个动态规划问题,但我无法解决它。有人能帮我解决这个问题吗?
编辑-
有没有办法以O(N2)或更少的时间复杂度解决这个问题。
最近在面试中,我被问到了下面这个问题。
给定一个字符串S,我需要找到另一个字符串S2,使得S2是S的一个子序列,并且S也是S2+reverse(S2)的一个子序列。这里的“+”表示字符串连接。我需要输出给定S情况下S2的最小长度。
我被告知这是一个动态规划问题,但我无法解决它。有人能帮我解决这个问题吗?
编辑-
有没有办法以O(N2)或更少的时间复杂度解决这个问题。
这个问题有两个重要方面。
子字符串
连接字符串
现在出现了一个重要的疑问。为什么我们只考虑从中心开始的左侧?答案很简单,连接字符串是由S+reverse(S)组成的。因此,我们可以确定子字符串中的最后一个元素在连接字符串中是连续的。没有任何重复出现在主字符串的前半部分可以给出更好的结果,因为至少我们应该有n个字母在最终连接的字符串中。String S ="locomotiffitomoc";
// as you see S2 string is "locomotif" but
// we don't know S2 yet, so it's blank
String S2 = "";
for (int a=0; a<S.length(); a++) {
try {
int b = 0;
while (S.charAt(a - b) == S.charAt(a + b + 1))
b++;
// if this for loop breaks that means that there is a character that doesn't match the rule
// if for loop doesn't break but throws an exception we found it.
} catch (Exception e) {
// if StringOutOfBoundsException is thrown this means end of the string.
// you can check this manually of course.
S2 = S.substring(0,a+1);
break;
}
}
System.out.println(S2); // will print out "locomotif"
字符串S中的每个字符可以包含在S2中或不包含。通过这样做,我们可以构建递归,尝试两种情况:
并计算这两个覆盖的最小值。为了实现这一点,只需跟踪已选择的S2+reverse(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
abacabca
的情况下似乎产生了错误的结果。它返回abcabca
,但最小的解决方案是abacab
。 - nneonneolen(with_char) >= len(without_char)
应该是 len(with_char) <= len(without_char)
:-/ 我现在正在更改它。 - Ante