繁体   English   中英

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

[英]Given a list of lists of strings, find most frequent pair of strings, second most frequent pair, ....., then most frequent triplet of strings, etc

我有一个包含 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' 是第二频繁的对。

您可以使用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)]

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

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}

在我的硬盘上找到一个片段,检查它是否对你有帮助:

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']

我有一个相当简单的方法,不使用任何库。
首先,对于主列表中的每个列表,我们可以计算每对字符串的哈希值。 (更多关于字符串散列在这里: 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”对的哈希值,并相应地将它们添加到字典中。 对主列表中的所有列表重复相同的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM