多序列的最长公共子序列

时间:2011-04-22 04:08:48

标签: c algorithm dynamic-programming

我已经做了一系列研究,找到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

3 个答案:

答案 0 :(得分:3)

一个简单的想法。

对于i1之间的每个数字N,计算最后一个数字为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)

答案 1 :(得分:2)

由于你有独特的元素,@ 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]并打印字符。如果没有,请根据上述值的最大值进行回溯。

答案 2 :(得分:1)

您可以查看“Design of a new Deterministic Algorithm for finding Common DNA Subsequence”论文。您可以使用此算法构建DAG(第8页,图5)。从DAG中,读取最大的常见不同子序列。然后使用M的值尝试动态编程方法,以确定每个序列需要构建多少DAG。基本上使用这些子序列作为键并将相应的序列号存储在找到的位置,然后尝试找到最大的子序列(可以超过1)。