数据库中最常见的单词

时间:2012-09-21 06:41:32

标签: algorithm bigdata

我遇到了一个问题,我们必须找到一个TB级文件或字符串中最常用的10个单词。

我能想到的一个解决方案是使用哈希表(word,count)和最大堆。但如果单词是唯一的,那么拟合所有单词可能会导致问题。 我想到了通过在不同节点上拆分块来使用Map-Reduce的另一种解决方案。 另一种解决方案是为所有单词构建Trie,并在扫描文件或字符串时更新每个单词的计数。

上述哪一种更好的解决方案?我认为第一个解决方案很天真。

4 个答案:

答案 0 :(得分:5)

将可用内存分成两半。使用一个作为4位counting Bloom filter,另一半作为具有计数的固定大小哈希表。计数Bloom过滤器的作用是过滤掉具有高内存效率的很少出现的单词。

检查最初为空的Bloom过滤器的1 TB字样;如果一个单词已经存在并且所有存储桶都设置为最大值15(这可能部分或完全是误报),则将其传递通过。如果不是,请添加它。

通过的词被计算;对于大多数单词而言,这是每次,但前15次你看到它们。一小部分人将开始更快地计算,每个单词最多可能出现15次不准确的结果。这是Bloom过滤器的限制。

当第一次传球结束时,如果需要,您可以通过第二次传球来纠正不准确性。取消分配Bloom过滤器,还释放所有不在第十个最常用单词后面15次内的计数。再次浏览输入,这次准确计算单词(使用单独的哈希表),但忽略第一遍中未保留为近似获胜者的单词。

备注

第一遍中使用的哈希表理论上可能会溢出输入的某些统计分布(例如,每个字恰好16次)或具有非常有限的RAM。您可以自行计算或尝试是否可以实际发生这种情况。

另请注意,铲斗宽度(上述说明中的4位)只是结构的参数。一个不计数的Bloom过滤器(桶宽度为1)可以很好地过滤掉大多数独特的单词,但不会过滤掉其他很少出现的单词。较宽的桶大小将更容易在单词之间进行串扰(因为将有更少的桶),并且它还将在第一次通过后降低保证的准确度水平(在4位的情况下发生15次)。但是这些缺点在某种程度上在数量上是微不足道的,而我正在想象更具侵略性的过滤效果对于使用非重复的自然语言数据将哈希表保持在亚兆字节大小是至关重要的。

Bloom过滤器本身的数量级内存需求; these people的工作方式低于100 MB,并且具有更具挑战性的应用程序(“完整”n-gram统计数据,而不是1-gram阈值统计数据)。

答案 1 :(得分:3)

使用mergesort按字母顺序对TB级文件进行排序。在初始传递中,使用所有可用物理RAM进行快速排序,以预先对长长的单词进行排序。

这样做时,只用一个这样的单词和一个计数代表连续的相同单词序列。 (也就是说,您在合并期间添加计数。)

然后使用带有快速排序预分类的mergesort再次使用该文件,但这次是按计数而不是按字母顺序排列。

这比我的其他答案更慢但更容易实现。

答案 2 :(得分:2)

我能想到的最好的:

  1. 将数据拆分为可存储在内存中的部分。
  2. 每个部分获得N最常用的字词,您将获得N * partsNumber个字词。
  3. 再次读取所有数据,计算您之前获得的单词。
  4. 它并不总能给你正确答案,但它可以在固定内存和线性时间内工作。

答案 3 :(得分:0)

为什么您认为建造Trie结构不是最佳决定?用计数器标记所有子节点,仅此而已!最大内存复杂度将为O(26 * longest_word_length),而时间复杂度应为O(n),这还不错,是吗?