给定一个单词列表,标识长度为4或更大的所有相同子串

时间:2012-08-06 05:46:50

标签: python algorithm counter frequency

假设我有一个外国词汇列表:

  1. ilikuwa
  2. alikuwa
  3. nilifundisha
  4. anafundisha
  5. tunasoma
  6. tulisoma
  7. 我想在这个单词列表中识别单词中常见的长度为4或更大的子串。例如,“kuwa”,“fundisha”和“soma”这两个词都属于这一类。

    然后,当我进行频率分析时:

    cnt = Counter()
    for lines in list:
        cnt[words]
    print cnt.most_common(2000)
    

    我希望将这些子字符串计算在它们出现在整个列表中的次数...这样:print cnt.most_common(3)的最终输出就像是。

    1. kuwa - 2
    2. fundisha - 2
    3. soma-2
    4. ilikuwa- 1 ...等
    5. 但是,我完全不知道如何去做这件事。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

你已经使用了Counter,所以缺少的是一种生成任何给定字符串的子串的方法。如果该位在某个函数的某个位置,它接受一个字符串和一个子字符串的最小长度,那么在itertools.chain的帮助下,您的计数逻辑可以是一个单行程:

cnt = Counter(chain.from_iterable(substrings(line, 4) for line in lines))
cnt.most_common(2000)

这就留下了解决如何生成这些子串的问题。最简单的方法是循环遍历可能的子串大小,然后遍历字符串并从字符串中的每个连续位置开始返回切片,并具有给定的长度(但是因为Python中的切片需要一个开始和一个结束索引,我们需要做一些切片算法来使其工作):

def substrings(s, min_length=1):
   for length in range(min_length, len(s)+1):
     for start in range(len(s) - min_length + 1):
        yield s[start:start+length]

答案 1 :(得分:1)

如果效率很重要,我相信你需要一个Suffix Array

如wiki所示,使用后缀数组,您可以计算O(m + logN)中任何子字符串的出现次数,其中m是子字符串的长度,N是所有单词的总长度。

但是你还需要列举每个单词的所有子串。在最坏的情况下,我不认为O(N * N)枚举是可以避免的。但是使用dict()来避免重复子串的多次检查肯定会改善平均情况下的性能。