找出一本大书中最常用的 10 个单词 [重复]
Posted
技术标签:
【中文标题】找出一本大书中最常用的 10 个单词 [重复]【英文标题】:Find the 10 most frequently used words in a large book [duplicate] 【发布时间】:2013-07-06 16:35:21 【问题描述】:我知道这已经在论坛上被问过几次,我没有找到任何可以被认为是最合适的解决方案的“标记”答案 - 所以再次询问:
我们从书中得到了一个非常大的文本,所有这些都无法放入记忆中。我们需要找到文本中出现频率最高的 10 个单词。执行此操作的最佳(时间和空间)方式是什么?
我的想法:
将文件分成 k 个大小的块(这样每个块都可以存储在内存中)。现在,对每个块执行外部排序。一旦我们在磁盘上有 (N/k)- 排序的文件(假设 N 是书中文本的总大小) - 我不知道应该如何继续,以便我可以从k 排序数组。
另外,如果有不同的思路,请提出建议。
【问题讨论】:
到目前为止您尝试过什么?你都有些什么想法呢?您不应该在没有先思考和努力的情况下在这里发布家庭作业问题。 每当你发现自己迷路时,排序一条出路! (: 我确实看过那里发布的解决方案,我正在寻找更多的算法解决方案,而不是 linux 'sort -u' kinda hack。我已经考虑过了,并在这个问题上发表了我的想法。 【参考方案1】:这是流算法领域的经典问题。在某些退化的情况下,显然没有办法做到这一点。您需要适应一堆大约(在明确定义的意义上)流中前 k 个单词的元素。我不知道任何经典的参考资料,但一个快速的谷歌将我带到了this。它似乎对进行流式 top-K 的各种技术进行了很好的调查。您可以查看其中的参考资料以了解其他想法。
另一种想法(并且在流模型中不适用)只是随机采样尽可能多的单词以适合内存,对它们进行排序和唯一化,然后再次遍历文件计数命中示例中的单词。然后就可以轻松找到前k了。
【讨论】:
【参考方案2】:编辑:此算法存在问题,特别是递归合并列表使其成为多项式运行时算法。但我将把它作为一个有缺陷的算法的例子留在这里。
您不能从块中丢弃任何单词,因为可能有一个单词仅在一个块中存在 100 次,而另一个单词在 100 个不同块中的每个块中都存在一次。
但是您仍然可以使用类似于MapReduce 算法的方式使用块。您将每个块映射到一个单词列表(包括计数),然后通过递归地将单词列表合并为一个来减少。
在映射步骤中,将每个单词映射到每个块的计数。 按字母顺序排序,而不是按计数并将列表存储到磁盘。现在您可以成对线性合并列表,而无需在内存中保留两个以上的单词:
-
令 A 和 B 为要合并的列表文件,R 为结果文件
从A中读取一行单词+count,调用单词
a
从B中读取一行单词+count,调用单词b
按字母顺序比较单词:
如果a
= b
:
合计他们的计数
将单词和新计数写入 R
转到2
如果a
> b
:
将b
包括其计数写入R
从 B 读取一个新行 b
转到4
如果a
b:
将a
包括其计数写入R
从A读取一个新行a
转到4
继续进行这种成对合并,直到所有文件合并到一个列表中。然后您可以扫描一次结果列表并保留最常用的十个单词。
【讨论】:
以上是关于找出一本大书中最常用的 10 个单词 [重复]的主要内容,如果未能解决你的问题,请参考以下文章