最常见的词

时间:2010-04-08 14:17:19

标签: java

Java中最有效的方法是使用频率从文本中获取50个最常用的单词?

我想搜索大约1,000,000个文本,每个文本大约有10,000个单词,希望它能在合理的时间范围内工作。

4 个答案:

答案 0 :(得分:8)

效率最高的可能是使用链接到Patricia triemax-heap。每当你在trie上读到一个单词find时,就转到堆和increase-key。如果它不在trie中,add并将其密钥设置在堆中。

使用Fibonacci heapincrease-keyO(1)


一个不太合理的解决方案是使用Map<String, Integer>,每次遇到一个单词时添加计数,然后根据计数对其entrySet()进行自定义排序以获得前50名。< / p>

如果O(N log N)排序不可接受,请使用selection algorithm查找O(N)中的前50名。


哪种技术更好取决于您的要求(即评论这是[algorithm]问题还是[java]问题非常明显)。

Map<String, Integer>后跟选择算法是最实用的,但Patricia trie解决方案明显优于空间效率(因为公共前缀不会冗余存储)。

答案 1 :(得分:4)

遵循伪代码应该可以解决问题:

build a map<word, count>
build a tokenizer that gives you a word per iteration
for each word*,
   if word in map, increment its count
   otherwise add with count = 1
sort words by count
for each of the first 50 words,
   output word, frequency = count / total_words

这基本上是O(N),以及jpabluz建议的内容。但是,如果您打算在任何“野外”文本中使用它,您会注意到大量垃圾:大写/小写,标点符号,URL,停止词,如'the'或'和',非常高计数,同一个单词的多个变体...正确的方法是将所有单词小写,删除所有标点符号(以及URL等内容),并在标有星号的点处添加停用词删除和词干。上面的伪代码。

答案 2 :(得分:0)

你最好的机会是一个O(n)算法,我会选择一个文本阅读器来分割单词,然后将它添加到一个有序的树中,你可以按照外观的顺序排序并将它们链接到一个字。之后,只需进行50次迭代遍历即可获得最高值。

答案 3 :(得分:0)

O(n)

  1. 计算单词数
  2. 将文字明智地分成单词列表
  3. 创建word =&gt; number_of_occurences
  4. 的地图
  5. 遍历地图并选择最大值。 50。
  6. 将它们除以总字数以获得频率
  7. 当然,根据您将使用的数据结构,某些步骤可能同时完成或不必要。