网上有大量关于最常见的子序列问题的文献,但我的问题略有不同,并且想知道是否有人知道快速算法。
说,你有一系列路径:
[1,2,3,4,5,6,7],[2,3,4,9,10],[3,4,6,7],......
我们看到子路径[3,4]是最常见的。
知道一个简洁的算法来找到它吗?对于我的情况,有成千上万的路径!
答案 0 :(得分:2)
假设"路径"必须包含至少两个元素,然后最常见的路径显然将具有两个元素(尽管也可能存在具有两个以上元素的路径,这些元素同样常见 - 稍后将详细介绍)。因此,您可以迭代所有列表并计算每对连续数字出现在不同列表中的频率,并记住最常出现的那些对。这需要迭代每个列表一次,这是您在任何情况下必须做的最小量。
如果您对最长最常见的路径感兴趣,那么您可以以相同的方式开始,找到最常见的2段路径,但除了计数外,还记录位置每个段(例如,示例中为{(3,4): [2, 1, 0], ...}
,列表中的数字表示段在不同路径中的位置)。现在,您可以采用所有最常见的长度为2的路径,并查看对于其中任何一个,下一个元素对于所有该路径的出现也是相同的。在这种情况下,您有一个最常见的长度为3的路径,它与先前的长度为2的路径一样常见(显然,它不能更多常见)。您可以对长度为4,长度为5等重复此操作,直到无法再进行扩展而不会使路径变得不那么常见&#34;。这部分需要为每次扩展额外完成 n * k 的工作,其中 n 是剩下的候选人数, k 出现的频率。< / p>
(这假设频率超过长度,即如果长度为2的路径出现三次,则您更喜欢在长度为3的路径上出现两次。相同的apprach也可以用于不同的起始长度,例如至少要求长度为3的路径,而不改变基本算法或复杂性。)
这是Python中用于演示算法的简单示例实现。这只能达到3长度,但可以通过循环轻松扩展到4长度以上。此外,它不会检查任何边缘情况(数组越界等)
# example data
data = [[1,2, 4,5,6,7, 9],
[1,2,3,4,5,6, 8,9],
[1,2, 4,5,6,7,8 ]]
# step one: count how often and where each pair appears
from collections import defaultdict
pairs = defaultdict(list)
for i, lst in enumerate(data):
for k, pair in enumerate(zip(lst, lst[1:])):
pairs[pair].append((i,k))
# step two: find most common pair and filter
most = max([len(lst) for lst in pairs.values()])
pairs = {k: v for k, v in pairs.items() if len(v) == most}
print(pairs)
# {(1, 2): [(0, 0), (1, 0), (2, 0)], (4, 5): [(0, 2), (1, 3), (2, 2)], (5, 6): [(0, 3), (1, 4), (2, 3)]}
# step three: expand pairs to triplets, triplets to quadruples, etc.
triples = [k + (data[v[0][0]][v[0][1]+2],)
for k, v in pairs.items()
if len(set(data[i][k+2] for (i,k) in v)) == 1]
print(triples)
# [(4, 5, 6)]