假设我有一个外国词汇列表:
我想在这个单词列表中识别单词中常见的长度为4或更大的子串。例如,“kuwa”,“fundisha”和“soma”这两个词都属于这一类。
然后,当我进行频率分析时:
cnt = Counter()
for lines in list:
cnt[words]
print cnt.most_common(2000)
我希望将这些子字符串计算在它们出现在整个列表中的次数...这样:print cnt.most_common(3)的最终输出就像是。
答案 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()来避免重复子串的多次检查肯定会改善平均情况下的性能。