我试图从多个固定长度字符串的相同位置找到所有可能最长的公共子序列(总共有700个字符串,每个字符串有25个字母)。最长的公共子序列必须包含至少3个字母,并且至少属于3个字符串。如果我有:
String test1 = "abcdeug";
String test2 = "abxdopq";
String test3 = "abydnpq";
String test4 = "hzsdwpq";
我需要的答案是:
String[] Answer = ["abd", "dpq"];
我的一个问题是这需要尽可能快。我试图用后缀树找到答案,但后缀树方法的解决方案是["ab","pq"]
。后缀树只能从多个字符串中找到连续的子字符串。常见的最长公共子序列算法无法解决这个问题。
有没有人知道如何以较低的时间成本解决这个问题?
感谢
答案 0 :(得分:1)
我建议你在尝试使用听起来像你想要的任何算法之前将其转换为众所周知的计算问题。
以下是我的建议:将此转换为图形问题。对于字符串中的每个位置,您将创建一组节点(一个节点用于集合中所有字符串中该位置的每个唯一字母...如果所有700个字符串在相同位置不同,则为700个节点)。一旦为字符串中的每个位置创建了所有节点,就会通过一组字符串查看两个位置共享3个以上相等连接的频率。在您的示例中,我们首先查看位置1和2,并看到三个字符串在位置1中包含“a”而在位置2中包含“b”,因此我们在第一组节点中的节点“a”之间添加有向边图中的“b”和第二组节点中的“b”(对于所有位置对和这两个位置中的所有字母组合继续这样做)。您为每个职位组合执行此操作,直到您添加了所有必要的链接。
获得最终图表后,您必须寻找最长的路径;我建议在这里查看维基百科文章:Longest Path。在我们的例子中,我们将有一个有向无环图,你可以在线性时间内解决它!预处理应该是字符串位置的二次方,因为我想你的字母表是固定大小的。
P.S:你给我发了一封关于我正在研究的双聚类算法的电子邮件;它尚未发布,但今年某个时候可以使用(手指交叉)。感谢您的兴趣,但是:)
答案 1 :(得分:0)
您可以尝试使用散列
每个字符串最多包含25个字符。这意味着它有2 ^ 25个子序列。你取每个字符串,计算所有2 ^ 25个哈希值。然后加入所有字符串的所有哈希值并计算其中至少包含3次。
为了获得这些子序列的长度,您不仅需要存储哈希值,还需要存储<hash, subsequence_pointer>
对,其中subsequence_pointer
确定该哈希的子序列(最简单的方法是枚举所有字符串的所有哈希值和存储哈希数)
基于算法,最坏情况下的程序(700个字符串,每个字符25个字符)将运行几分钟。