我可以使用动态编程以正确的方式执行此操作,但我无法弄清楚如何在指数时间内完成此操作。
我正在寻找两个字符串之间最大的公共子序列。 注意:我的意思是子序列而不是子串,构成序列的符号不必是连续的。
答案 0 :(得分:6)
只需使用递归调用替换动态编程代码中表中的查找。换句话说,只需实现LCS问题的递归表达式:
修改强>
在伪代码中(几乎是python,实际上):
def lcs(s1, s2):
if len(s1)==0 or len(s2)==0: return 0
if s1[0] == s2[0]: return 1 + lcs(s1[1:], s2[1:])
return max(lcs(s1, s2[1:]), lcs(s1[1:], s2))
答案 1 :(得分:1)
假设您有两个长度为a
的字符串b
和n
。最长的公共子序列将是字符串a
中最长的子序列,它也存在于字符串b
中。
因此,我们可以遍历a
中所有可能的子序列,并看到它位于b
。
对此的高级伪代码将是:
for i=n to 0
for all length i subsequences s of a
if s is a subsequence of b
return s
答案 2 :(得分:1)
字符串A和字符串B.递归算法,也许它很幼稚,但很简单:
查看A的第一个字母。这将是一个共同序列或不同。在考虑'not'选项时,我们会剪掉第一个字母并递归调用。当考虑''在一个共同的序列'选项时,我们也将它修剪掉,我们也从B的开头到B.并包括在B中的相同字母。一些伪代码:
def common_subsequences(A,B, len_subsequence_so_far = 0):
if len(A) == 0 or len(B) == 0:
return
first_of_A = A[0] // the first letter in A.
A1 = A[1:] // A, but with the first letter removed
common_subsequences(A1,B,len_subsequence_so_far) // the first recursive call
if(the_first_letter_of_A_is_also_in_B):
Bn = ... delete from the start of B up to, and including,
... the first letter which equals first_of_A
common_subsequences(A1,Bn, 1+len_subsequence_so_far )
你可以从那开始,然后通过记住到目前为止找到的最长子序列进行优化,然后在当前函数无法击败时(即min(len(A), len(B))+len_subsequence_so_far
小于到目前为止找到的最长长度时返回)。 / p>
答案 3 :(得分:0)
基本上如果你不使用动态编程范例 - 你会达到指数时间。这是因为,通过不存储您的部分值 - 您将多次重新计算部分值。
答案 4 :(得分:0)
为了达到指数时间,它足以生成两个阵列的所有子序列并将每个阵列相互比较。如果匹配两个相同的检查它们的长度是否大于当前最大值。伪代码将是:
Generate all subsequences of `array1` and `array2`.
for each subsequence of `array1` as s1
for each subsequece of `array2` as s2
if s1 == s2 //check char by char
if len(s1) > currentMax
currentMax = len(s1)
for i = 0; i < 2^2; i++;
绝对不是最佳。它甚至没有尝试过。然而问题是关于效率非常低的算法,所以我提供了一个。
答案 5 :(得分:-1)
int lcs(char[] x, int i, char[] y, int j) {
if (i == 0 || j == 0) return 0;
if (x[i - 1] == y[j - 1]) return lcs(x, i - 1, y, j - 1) + 1;
return Math.max(lcs(x, i, y, j - 1), lcs(x, i - 1, y, j));
}
print(lcs(x, x.length, y, y.length);
以下是部分递归树:
lcs("ABCD", "AFDX")
/ \
lcs("ABC", "AFDX") lcs("ABCD", "AFD")
/ \ / \
lcs("AB", "AFDX") lcs("AXY", "AFD") lcs("ABC", "AFD") lcs("ABCD", "AF")
最坏的情况是当LCS的长度为0时,这意味着没有共同的子序列。在这种情况下,将检查所有可能的子序列,并且有O(2^n)
个子序列。