搜索另一个大型列表中的大量单词列表

时间:2010-03-31 23:31:39

标签: search

我有一个1,000,000个字符串的排序列表,最大长度为256个,带有蛋白质名称。每个字符串都有一个关联的ID。 我有另一个未分类的4,000,000,000个字符串列表,最大长度为256,文章中的单词和每个单词都有一个ID。

我想找到蛋白质名称列表和文章单词列表之间的所有匹配项。 我应该使用哪种算法?我应该使用一些prebuild API吗?

如果算法在没有特殊硬件的普通PC上运行会很好。

算法所需的时间估计会很好,但不是强制性的。

5 个答案:

答案 0 :(得分:1)

40亿个字符串是很多要搜索的字符串。

您可以将整个数据结构放入内存哈希中以便快速查找,但更有可能您希望将整个列表存储在更宽敞(但速度更慢)的磁盘上,在这种情况下,排序列表会自行调整相对有效的二进制搜索算法。

如果您的二进制搜索或此类函数被称为find_string_in_articles(),则伪代码:

foreach $protein_name ( @protein_names ) {
    if ( $article_id = find_string_in_articles( $protein_name ) ) {
        print( "$protein_name matches $article_id\n" );
    }
}

答案 1 :(得分:1)

您可以对它们进行排序,然后执行“mergesort”,它实际上不会合并但会发现重复/重叠。维基百科对此有很好的参考。

对该数据量进行排序可能需要比您可访问的内存更多的内存。我不知道unix排序(在Windows / Mac上也可以)可以处理,但任何体面的SQL数据库都可以做到。

另一种可能性是在蛋白质名称上使用基数树(以A开头的那些转到bin A,B转到bin B等)。然后只需循环遍历4亿个单词并找到重叠(您可能必须实施多个深度基数合并以一次丢弃更多蛋白质)。

答案 2 :(得分:1)

这实际上是一种关系连接。假设您尚未对文章单词进行排序,则基本算法应为:

for word in article_words:
    if (proteins.find(word)):
        found_match(word)

proteins.find()是困难的部分,你必须尝试获得最佳性能,这类问题是缓存效果开始发挥作用的地方。我首先尝试使用基数排序,它非常简单并且可能足够快,但二进制搜索和散列也是替代方案。

答案 3 :(得分:0)

听起来像你应该使用二叉树的东西。

答案 4 :(得分:0)

我会以两种方式之一来解决这个问题。

  1. 将其插入sql数据库并提取所需的数据(更慢,但更容易)
  2. 对列表进行排序,然后进行二进制搜索以找到您需要的内容(快速,但很棘手)