【问题标题】:Efficient algorithm to find most common phrases in a large volume of text在大量文本中查找最常用短语的高效算法
【发布时间】:2013-11-06 11:16:12
【问题描述】:

我正在考虑编写一个程序来为我收集大量文本中最常见的短语。如果将问题简化为仅查找单词,那么就像将每个新单词存储在哈希图中然后增加每次出现的计数一样简单。但是对于短语,将句子的每个排列存储为键似乎是不可行的。

基本上,问题被缩小到弄清楚如何从足够大的文本中提取每个可能的短语。计算短语然后按出现次数排序变得微不足道。

【问题讨论】:

  • 也许你可以研究一下类似 trie 的东西?一个节点在哪里也存储它的出现,沿着 trie 的路径形成一个短语?
  • 把你的最后一段作为真正的问题,也许你的问题只是定义一个短语是什么。如果这是问题所在,请考虑使用 NLTK 之类的自然语言处理工具。在这种情况下,提取短语的对象称为“chunker”。
  • 一个短语有多长?无论您是在做一个单词的短语还是 10 个单词的短语,算法都几乎相同。唯一的区别是您必须处理的数据量。

标签: algorithm data-structures frequency frequency-analysis word-frequency


【解决方案1】:

我假设您正在搜索以相同顺序出现的连续单词的常见模式(例如,“top of the world”不会被视为与“top of a world”或“the world of top”相同的短语)。

如果是这样,那么我会推荐以下线性时间方法:

  1. 将您的文本拆分成单词并删除您认为不重要的内容(即删除大写、标点、分词等)
  2. 将文本转换为整数数组(每个唯一单词一个整数)(例如,“cat”的每个实例变为 1,每个“dog”变为 2)这可以通过使用基于哈希的字典在线性时间内完成存储从单词到数字的转换。如果该词不在字典中,则分配一个新的 id。
  3. 为整数数组构造一个后缀数组(这是数组中所有后缀的排序列表,可以按线性时间构造 - 例如,使用算法和 C 代码 here
  4. 为您的后缀数组构造最长的公共前缀数组。 (这也可以在线性时间内完成,例如使用 C code)这个 LCP 数组给出了后缀数组中连续对之间每个后缀开头的常用词的数量。

您现在可以收集常用短语了。

目前还不清楚您希望如何确定短语的结尾。一种可能性是简单地收集所有重复的 4 个单词的序列。
这可以通过查看最长公共前缀数组 >= 4 的位置的后缀数组来在线性时间内完成。索引 x 在 [start+1...start+len] 范围内的每次运行,其中 LCP[ x] >= 4(除 x 的最后一个值之外的所有值)对应于重复 len 次的短语。短语本身由前 4 个单词给出,例如后缀 start+1。

请注意,这种方法可能会发现跨句尾的短语。您可能更愿意将一些标点符号(例如句号)转换为唯一的整数来防止这种情况发生。

【讨论】:

  • 我喜欢独特的词的想法,这是一件好事。在那之后,在线性时间内构造一个 sorted 后缀数组似乎是一项不可能的工作,因为排序是线性的(除非我遗漏了一些明显的东西)。另外,我认为您在回答错误的问题。问题是关于最常用的短语,而不是最长的常用短语。
  • 1) 我同意这个问题是关于最常见的短语。我的答案是找到 len ,它给出了一定数量单词的每个短语重复的次数。 2) 构造后缀数组的线性时间方法利用基数排序,避免了排序需要nlogn时间。
  • 只有当键的长度为O(1)时,基数排序在最坏的情况下才是线性的。您正在对n 键(后缀)进行排序,每个键的大小最多为n。键完全不同,它们的长度至少为log(n),因此基数排序的复杂性不能低于线性。
  • @naitoon:后缀数组中的项目不是任意的。还有it can be exploited to construct a suffix array augmented with lcp array in O(n).
猜你喜欢
  • 2011-03-21
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 2016-11-15
  • 1970-01-01
相关资源
最近更新 更多