我对搜索算法有疑问。我目前有2个纯文本文件,每个文件至少有1000万行。现在,每一行都是一个字符串,我想在第一个文件中找到同样出现在第二个文件中的每个字符串。有效地做到这一点有好方法吗?任何来自算法或特殊语言功能的建议都表示赞赏。
答案 0 :(得分:14)
如果您对文件的结构一无所知(例如它们是否已经排序),您可以采取许多不同的方法来解决问题,这取决于您对内存的限制和空间使用,可能是你正在寻找的。 p>
如果你有可用的空闲RAM,一个选项是在内存中创建一个哈希表来保存字符串。然后,您可以将第一个文件中的所有字符串加载到哈希表中。然后,一次一个地加载第二个文件中的每个字符串。对于每个字符串,检查它是否在哈希表中。如果是,请举报比赛。这种方法使用O(m)内存(其中m是第一个文件中的字符串数)并且至少需要Ω(m + n)个时间,甚至可能更多,具体取决于散列函数的工作方式。这也是(几乎可以肯定)解决问题的最简单,最直接的方法。
如果没有足够的RAM,但时间不是很大的限制,您可以使用第一个算法的修改版本。从第一个文件中选择要加载的一些行数。然后,将这些字符串加载到哈希表中。完成此操作后,扫描整个第二个文件以查找任何匹配项。然后,从哈希表中逐出所有行并加载第一个文件中的下一行行并重复。这具有运行时Ω(mn / b),其中b是块大小(因为对于第二文件中的所有n个字节的完整线性扫描存在O(m / b)次迭代)。或者,如果您知道一个文件比另一个文件小得多,您可能要考虑将整个文件加载到内存中,然后扫描另一个文件。
如果你没有足够的RAM可用但是能够耗尽更多的磁盘空间,一个选项可能是使用external sorting algorithm对这两个文件中的每一个进行排序(或者,至少,构造一个目录,按排序顺序列出每个文件的行)。按文件排序后,您可以并行浏览它们,查找所有匹配项。这使用更通用的算法来查找两个排序范围内的所有重复元素,其工作方式如下:
此算法大约需要O(n log n)时间对两个文件进行排序,然后进行总共O(n)次比较,以便在列表中查找公共项目。但是,由于字符串比较不一定在O(1)时间内运行(事实上,它们通常需要更长时间),因此实际运行时间可能要大得多。如果我们假设每个文件由n个长度为m的字符串组成,那么排序的运行时间将为O(mn log n),因为每个比较需要O(m)时间。类似地,比较步骤可能花费O(mn)时间,因为每个字符串比较也可能花费O(m)时间。作为一种可能的优化,您可能需要考虑计算一个小的哈希码(比如16或32位)。假设哈希码提供了良好的一致性,这可以大大减少比较字符串所需的时间,因为大多数不相同的字符串将具有不同的哈希码,并且可以在O(1)时间内进行比较。
最后,如果文件的每一行都相当长(例如,至少8个字符),则一个选项可能是为文件的每一行计算64位或更大的哈希值。然后,您可以使用上述任何技术来尝试查看是否在两个文件中重复使用任何哈希码(将所有内容保存在哈希表中,使用外部排序等)。假设您的哈希代码中有足够的位,冲突的数量应该很少,你应该能够快速找到匹配并且内存使用量更少。
希望这有帮助!
哇噢!这是我在Stack Overflow上的第1000个答案! : - )