【问题标题】:Longest Common Subsequence for Multiple Sequences多个序列的最长公共子序列
【发布时间】:2011-08-10 18:24:29
【问题描述】:

我已经做了大量研究来寻找 M = 2 序列的最长序列,但我正在尝试找出 M ≥ 2 序列的最长方法

我得到 N 和 M: M 个序列,具有 N 个唯一元素。 N 是 {1 - N} 的集合。我已经考虑过动态编程方法,但我仍然对如何实际合并它感到困惑。

输入示例

5 3
5 3 4 1 2
2 5 4 3 1
5 2 3 1 4

这里的最大序列可以看出是

5 3 1

预期输出

Length = 3

【问题讨论】:

  • 您能发布您迄今为止尝试过的方法吗?从那里我们可以为您指明正确的方向..
  • M 是子序列必须存在的序列数?
  • @Jerry 第一行指定 N 和 M。这对于 C 竞赛/作业问题规范来说是正常的 :)
  • @Karl:好的——知道了。谢谢。

标签: c algorithm dynamic-programming


【解决方案1】:

您可以查看“Design of a new Deterministic Algorithm for finding Common DNA Subsequence”论文。您可以使用此算法来构造 DAG(第 8 页,图 5)。从 DAG 中,读取最大的常见不同子序列。然后尝试一种动态规划方法,使用 M 的值来决定每个序列需要构建多少个 DAG。基本上就是把这些子序列作为key,把对应的序列号存放在找到的地方,然后尝试找到最大的子序列(可以大于1)。

【讨论】:

    【解决方案2】:

    一个简单的想法。

    对于1N 之间的每个数字i,计算最后一个数字为i 的最长子序列。 (姑且称之为a[i]

    为此,我们将在第一个序列中从头到尾遍历数字 i。如果a[i] > 1,则有j,这样在每个序列中它都在i之前。
    现在我们可以检查j 的所有可能值并(如果之前的条件成立)做a[i] = max(a[i], a[j] + 1)

    作为最后一位,因为j在第一个序列中在i之前,这意味着a[j]已经计算好了。

    for each i in first_sequence
        // for the OP's example, 'i' would take values [5, 3, 4, 1, 2], in this order
        a[i] = 1;
        for each j in 1..N
            if j is before i in each sequence
                a[i] = max(a[i], a[j] + 1)
            end
        end
    end
    

    如果你事先计算出位置矩阵,那就是O(N^2*M)

    【讨论】:

    • 我认为这基本上是正确的,但是您编写的伪代码令人困惑。看起来i 迭代了序列列表,但它不应该从1 迭代到N 吗?我猜你认为sequences[0] 是第一个序列,因此包含所有元素1 .. N,但我认为像j 那样写出来更清楚。
    • @IVlad 是的,它应该迭代从 1 到 N 的所有数字,但也要以正确的顺序。但你是对的,伪代码令人困惑。我已经澄清了一点。不确定是否可以更好地呈现“订单”要求。
    • 非常感谢,我花了一点时间才明白这里发生了什么,但现在说得通了。
    【解决方案3】:

    由于您有独特的元素,@Nikita Rybak 的答案是可以使用的,但是由于您提到了动态编程,因此当您有两个以上的序列时,您将如何使用 DP:

    dp[i, j, k] = length of longest common subsequence considering the prefixes
                  a[1..i], b[1..j], c[1..k].
    
    
    dp[i, j, k] = 1 + dp[i - 1, j - 1, k - 1] if a[i] = b[j] = c[k]
                = max(dp[i - 1, j, k], dp[i, j - 1, k], dp[i, j, k - 1]) otherwise
    

    要取回实际的子序列,请使用从dp[a.Length, b.Length, c.Length] 开始的递归函数,基本上颠倒上述公式:如果三个元素相等,则回溯到dp[a.Length - 1, b.Length - 1, c.Length - 1] 并打印字符。如果不是,则根据上述值的最大值回溯。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      相关资源
      最近更新 更多