Algorithm 在大量文本中查找最常用短语的高效算法

Algorithm 在大量文本中查找最常用短语的高效算法,algorithm,data-structures,frequency,frequency-analysis,word-frequency,Algorithm,Data Structures,Frequency,Frequency Analysis,Word Frequency,我正在考虑写一个程序来收集大量文本中最常见的短语。如果将问题简化为仅查找单词,那么就可以将每个新词存储在hashmap中,然后增加每次出现的次数。但对于短语,将句子的每个排列存储为键似乎是不可行的 基本上,问题缩小到如何从足够大的文本中提取每个可能的短语。对短语进行计数,然后根据出现的次数进行排序变得很简单。我假设您正在搜索以相同顺序出现的连续单词的常见模式(例如,“世界之巅”不会被视为与“世界之巅”或“世界之巅”相同的短语) 如果是这样,我建议采用以下线性时间方法: 把你的文本拆分成文字,删除

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


基本上,问题缩小到如何从足够大的文本中提取每个可能的短语。对短语进行计数,然后根据出现的次数进行排序变得很简单。

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

如果是这样,我建议采用以下线性时间方法:

把你的文本拆分成文字,删除你认为不重要的东西(即删除大写、标点符号、断字等)。
  • 将文本转换为整数数组(每个唯一单词一个整数)(例如,“cat”的每个实例变为1,每个“dog”变为2)这可以通过使用基于哈希的字典存储从单词到数字的转换,在线性时间内完成。如果单词不在词典中,则分配一个新id
  • 为整数数组构造后缀数组(这是数组中所有后缀的排序列表,可以通过线性时间构造-例如,使用算法和C代码)
  • 为后缀数组构造最长的公共前缀数组。(这也可以在线性时间内完成,例如使用线性时间)此LCP数组给出后缀数组中连续对之间每个后缀开始处的公共字数
  • 您现在可以收集常用短语

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


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

    也许您可以研究类似于trie的东西?其中一个节点也存储了它的引用,并且沿着trie的路径形成了一个短语?把你的最后一段作为真正的问题,也许你的问题只是定义一个短语是什么。如果是这个问题,考虑一个自然语言处理工具,如NLTK。在这种情况下,提取短语的对象称为“chunker”。短语有多长?无论你是在做一个单词的短语还是10个单词的短语,算法都差不多。唯一的区别是你必须处理的数据量。看看这里,我喜欢单字的想法,这是一件好事。在这之后,在线性时间内构造排序后缀数组通常看起来是不可能的,因为排序是线性的(除非我遗漏了一些明显的东西)。另外,我认为你回答错了问题。问题是关于最常用的短语,而不是最长的常用短语。1)我同意问题是关于最常用的短语。我的答案是找到len,它给出了一定数量单词的每个短语重复的次数。2) 构造后缀数组的线性时间方法使用基数排序,以避免排序需要nlogn时间。仅当键的长度为
    O(1)
    时,基数排序在最坏情况下才是线性的。您正在对
    n
    键(后缀)进行排序,每个键的大小最多为
    n
    。键都是不同的,它们的长度至少是
    log(n)
    ,因此基数排序的复杂性不能小于linearithmic。@naitoon:后缀数组中的项不是任意的。和。