根据给定的字符串列表列表,找到最频繁的字符串对,第二最频繁的字符串对.....,然后是最频繁的三元组字符串,等等

时间:2020-10-12 08:43:40

标签: python python-3.x algorithm data-structures

我有一个包含k个字符串列表的列表(这些k个列表中的每个列表都没有重复的字符串)。我们知道所有可能的字符串的并集(假设我们有n个唯一的字符串)。

我们需要找到的是:什么是最频繁的字符串对(即,这两个字符串在k个列表中出现得最多?)以及第二最频繁的字符串对,第三最频繁的字符串对,等。此外,我想知道最频繁的字符串三连音,第二次最频繁的字符串三连音,等等。

我能想到的唯一算法非常复杂,基本上要求解最频繁的对,我将列举n个字符串(O(n ^ 2))中所有可能的对,并对于它们中的每一个,检查有多少列表(O(k)),然后将结果排序以获得所需的数据,因此我的总体复杂度为O(n ^ 2.x),而忽略了最后一个排序。

有什么想法可以在时间上改进算法吗? (希望对三重弦和四重弦等效果很好)? python中的代码是最好的,但是详细的伪代码(以及相关的数据结构)或详细的一般思想也可以!

例如: 如果

myList=[['AB', 'AC', 'ACC'], ['AB','ACC'],['ACC'],['AC','ACC'],['ACC','BB','AC']], 

然后,对问题的预期输出将是:“ AC”,“ ACC”是最频繁的对,而“ AB”,“ ACC”是第二最频繁的对。

4 个答案:

答案 0 :(得分:2)

您可以使用combinationsCounterfrozenset

from itertools import combinations
from collections import Counter

combos = (combinations(i, r=2) for i in myList)
Counter(frozenset(i) for c in combos for i in c).most_common(2)

输出:

[(frozenset({'AC', 'ACC'}), 3), (frozenset({'AB', 'ACC'}), 2)]

答案 1 :(得分:1)

这是所有长度组合的通用解决方案:

import itertools
def most_freq(myList, n):
    d={} #create a dictionary that will keep pair:frequency
    for i in myList:
        if len(i)>=n:
            for k in itertools.combinations(i, n): #generates all combinations of length n in i
                if k in d: #increases the frequency for this pair by 1
                    d[k]+=1
                else:
                    d[k]=1
    return {k: v for k, v in sorted(d.items(), key=lambda item: item[1], reverse=True)}  #this just sorts the dictionary based on the value, in descending order

示例:

myList=[['AB', 'AC', 'ACC'], ['AB','ACC'],['ACC'],['AC','ACC'],['ACC','BB','AC']]

>>> most_freq(myList,2)
{('AB', 'ACC'): 2, ('AC', 'ACC'): 2, ('AB', 'AC'): 1, ('ACC', 'BB'): 1, ('ACC', 'AC'): 1, ('BB', 'AC'): 1}
>>> most_freq(myList,3)
{('AB', 'AC', 'ACC'): 1, ('ACC', 'BB', 'AC'): 1}

答案 2 :(得分:0)

在我的硬盘驱动器上找到了一个代码段,请检查它是否对您有帮助:

from collections import Counter
from itertools import combinations

mylist = [['AB', 'AC', 'ACC'], ['AB','ACC'],['ACC'],['AC','ACC'],['ACC','BB','AC']]
d  = Counter()
for s in mylist:
    if len(mylist) < 2:
        continue
    s.sort()
    for c in combinations(s,2):
        d[c] += 1

print(list(d.most_common()[0][0]))

将返回列表['AC','ACC']

答案 3 :(得分:0)

我有一个相当简单的方法,无需使用任何库。
首先,对于主列表中的每个列表,我们可以为每对字符串计算哈希值。 (有关字符串哈希的更多信息,请点击此处:https://cp-algorithms.com/string/string-hashing.html)。维护一个词典,其中保存每个发生的哈希的计数。最后,我们只需要对字典进行排序即可获得所有对,并按其出现次数排序。

示例:[['AB', 'AC', 'ACC', 'TR'], ['AB','ACC']]
对于列表1,即['AB', 'AC', 'ACC', 'TR']
计算“ AB AC”,“ AC ACC”,“ ACC TR”对的哈希,并相应地将它们添加到字典中。对主列表中的所有列表重复相同的操作。