【问题标题】:How can I find a faster algorithm for this special case of Longest Common Sub-sequence (LCS)?对于最长公共子序列 (LCS) 的这种特殊情况,如何找到更快的算法?
【发布时间】:2014-12-09 15:36:58
【问题描述】:

我知道 LCS 问题需要时间 ~ O(mn) 其中 m 和 n 分别是两个序列 X 和 Y 的长度。但我的问题稍微容易一些,所以我希望算法比 ~O(mn) 更快。

这是我的问题:

输入:

一个正整数Q,两个序列X=x1,x2,x3.....xn 和Y=y1,y2,y3...yn,长度均为n。

输出:

如果 X 和 Y 的 LCS 的长度至少为 n - Q,则为真;

否则为假。

众所周知的算法在这里花费 O(n^2),但实际上我们可以做得更好。因为每当我们在任一序列中消除多达 Q 个元素而没有找到共同元素时,结果都会返回 False。有人说应该有O(Q*n)这样好的算法,但我想不通。

更新: 已经找到答案了!

有人告诉我我可以只计算表 c[i,j] 的对角线块,因为如果 |i-j|>Q,则意味着两个序列中已经有超过 Q 个不匹配的元素。所以我们只需要计算|i-j|

【问题讨论】:

  • 所以本质上你只需要找到一个长度为 n-Q 的公共子序列,所以我们知道它必须从第一个 Q+1 位置开始。这一定会有所帮助。

标签: algorithm computer-science dynamic-programming lcs


【解决方案1】:

这是一种可能的方法:
1. 假设f(prefix_len, deleted_cnt)Y 中最左边的位置,这样Xprefix_len 元素已经被处理,而其中的deleted_cnt 正好被删除。显然,只有O(N * Q) 状态,因为deleted_cnt 不能超过Q
2. 基本情况是f(0, 0) = 0(没有处理任何内容,因此没有删除任何内容)。
3. 过渡:
a) 移除当前元素:f(i + 1, j + 1) = min(f(i + 1, j + 1), f(i, j)).
b) 将当前元素与Y 中与它相等且位于f(i, j) 之后的最左边可能的元素匹配(假设它具有索引pos):f(i + 1, j) = min(f(i + 1, j), pos)
4. 所以剩下的唯一问题是如何从给定位置获取位于右侧的最左侧匹配元素。让我们预先计算以下对:(Y 中的位置,X 的元素)->Y 的元素的最左边出现等于 X 的这个元素在Y 中的这个位置的右边和将它们放入哈希表中。它看起来像O(n^2)。但不是。对于Y 中的固定位置,我们永远不需要比Q + 1 位置更靠右。为什么?如果我们走得更远,我们会跳过更多 Q 元素!所以我们可以利用这个事实只检查O(N * Q) 对并获得所需的时间复杂度。当我们有这个哈希表时,在第 3 步中找到pos 只是一次哈希表查找。这是这一步的伪代码:

map = EmptyHashMap()
for i = 0 ... n - 1:
    for j = i + 1 ... min(n - 1, i + q + 1)
        map[(i, Y[j])] = min(map[(i, Y[j])], j)

不幸的是,这个解决方案使用哈希表,所以它的平均时间复杂度为O(N * Q),不是最坏的情况,但它应该是可行的。

【讨论】:

  • 谢谢!这个方法很棒。然而,有人告诉我我可以只计算表 c[i,j] 的对角线块,因为如果 |i-j|>Q,则意味着两个序列中已经有超过 Q 个不匹配的元素。所以我们只需要计算|i-j|
  • @ValarMorghulis 哦,是的。这真的很简单!我的解决方案看起来有点矫枉过正。
【解决方案2】:

你也可以说使字符串相等的过程成本不能大于Q。如果它大于Q,则答案必须为假。(编辑距离问题)

假设字符串x的大小为m,字符串y的大小为n,那么我们创建一个二维数组d[0..m][0..n],其中d[i][j]表示 x 的 i-length 前缀和 y 的 j-length 前缀之间的编辑距离。

数组 d 的计算是使用动态规划完成的,它使用以下递归:

d[i][0] = i , for i <= m
d[0][j] = j , for j <= n

d[i][j] = d[i - 1][j - 1], if s[i] == w[j],
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + 1), otherwise.

LCSif m&gt;n, m-dp[m][m-n]的回答

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2011-02-12
    相关资源
    最近更新 更多