如何计算最长公共子序列的数量

时间:2010-02-11 15:13:55

标签: algorithm lcs

我正在尝试计算两个字符串之间存在的最长可能子序列的数量

e.g。   String X =“efgefg”;   字符串Y =“efegf”;

输出:最长公共序列的数量为:3   (即:efeg,efef,efgf - 这不需要通过算法计算,这里只是为了演示而显示)

我已经设法在O(| X | * | Y |)中使用基于这里的一般想法的动态编程来做到这一点:Cheapest path algorithm

有人能想出一种有效运行更好的计算方法吗?

- 为回应杰森的评论而编辑。

4 个答案:

答案 0 :(得分:1)

最常见的子序列问题是一个研究得很好的CS问题。

您可以在此处阅读:http://en.wikipedia.org/wiki/Longest_common_subsequence_problem

答案 1 :(得分:0)

我不知道,但这里有一些大声思考的尝试:

我能够构建的最坏情况具有指数 - 2 **(0.5 | X |) - 最长公共子序列的数量:

X = "aAbBcCdD..."
Y = "AaBbCcDd..."

其中最长的公共子序列恰好包括{A,a}中的一个,恰好是{B,b}中的一个......等等(挑剔:如果你的字母表限制为256个字符,最终会破坏 - 但是2 ** 128已经很大了。)

但是,您不一定要生成所有子序列来计算它们。 如果你有O(| X | * | Y |),你已经比那更好了!我们从中学到的是任何比你更好的算法都不得试图生成实际的子序列

答案 2 :(得分:0)

首先,我们知道找到长度为n的两个序列的任何最长公共子序列都不能在O(n 2-ε)时间内完成,除非强指数时间假设失败,请参阅: https://arxiv.org/abs/1412.0348

这几乎意味着你不能计算在O(n 2-ε)时间内如何将公共子序列与输入序列对齐的方法。 另一方面,可以在O(n 2 )时间内计算这种比对的方式的数量。也可以用O(n 2 / log(n))时间计算它们,即所谓的四俄罗斯人加速。

现在真正的问题是你真的打算计算这个还是想找到不同的子序列的数量?我担心后者是#P完全计数问题。至少,我们知道计算具有常规语法可以生成的给定长度的序列数是#P-complete:

  

S上。 Kannan,Z。Sweedyk和S. R. Mahaney。数数   并以常规语言随机生成字符串。   在ACM-SIAM离散算法研讨会上   (SODA),第551-557页,1995年

这是一个类似的问题,在这个意义上,计算常规语法的 way 的数量可以生成给定长度的序列是一个简单的动态编程算法。但是,如果您不想区分产生相同序列的世代,那么问题就会变得容易到极其困难。我的自然猜想是序列对齐问题也应如此(最常见的子序列,编辑距离,最短的共同超弦等)。

因此,如果您想计算两个序列的不同子序列的数量,那么很可能您当前的算法是错误的,并且任何算法都无法在多项式时间内计算它,除非P = NP(及更多) ...)。

答案 3 :(得分:0)

最佳解释(附代码)我发现:

Count all LCS