Algorithm 路径集合中最常见的子路径

Algorithm 路径集合中最常见的子路径,algorithm,Algorithm,关于最长的公共子序列问题,网络上有很多文献,但我有一个稍微不同的问题,我想知道是否有人知道一个快速算法 例如,您有一组路径: [1,2,3,4,5,6,7],[2,3,4,9,10],[3,4,6,7] 我们看到子路径[3,4]是最常见的 知道一个简洁的算法来找到这个吗?就我而言,有成千上万条路径 假设一条“路径”必须包含至少两个元素,那么最常见的路径显然将包含两个元素(尽管也可能有一条路径包含两个以上相同的元素,稍后将详细介绍)。因此,您可以迭代所有列表,计算每对连续数字在不同列表中出现的频率

关于最长的公共子序列问题,网络上有很多文献,但我有一个稍微不同的问题,我想知道是否有人知道一个快速算法

例如,您有一组路径:

[1,2,3,4,5,6,7],[2,3,4,9,10],[3,4,6,7]

我们看到子路径[3,4]是最常见的

知道一个简洁的算法来找到这个吗?就我而言,有成千上万条路径

假设一条“路径”必须包含至少两个元素,那么最常见的路径显然将包含两个元素(尽管也可能有一条路径包含两个以上相同的元素,稍后将详细介绍)。因此,您可以迭代所有列表,计算每对连续数字在不同列表中出现的频率,并记住最常出现的那些数字对。这需要对每个列表迭代一次,这是在任何情况下都必须执行的最小数量

如果您对最长最常见的路径感兴趣,那么您可以以相同的方式开始,找到最常见的2段路径,但除了计数之外,还可以记录这些段的位置(例如,
{(3,4):[2,1,0],…}
在您的示例中,列表中的数字表示段在不同路径中的位置)。现在,您可以获取所有最常见的长度为2的路径,并查看是否对于其中任何一个路径,下一个元素对于该路径的所有引用也是相同的。在这种情况下,您有一个最常见的长度-3路径,它与前面的长度-2路径相同(显然,它不可能更常见)。您可以对length-4、length-5等重复此操作,直到无法在不使路径“不太常见”的情况下对其进行扩展。这一部分需要为每个扩展额外做n*k的工作,n是剩余的候选数量,k是这些候选数量出现的频率

(这假设频率拍长,即如果有一条长度为2的路径出现三次,则与长度为3的路径出现两次相比,您更喜欢这条路径。相同的方法也可用于不同的起始长度,例如,在不改变基本算法或复杂度的情况下,至少需要长度为3的路径。)


下面是一个用Python实现的简单示例来演示该算法。这只能扩展到长度-3,但可以通过循环轻松扩展到长度-4及更高。此外,它不会检查任何边缘情况(数组超出边界等)

#示例数据
数据=[[1,2,4,5,6,7,9],
[1,2,3,4,5,6,  8,9],
[1,2,  4,5,6,7,8  ]]
#第一步:计算每对出现的频率和位置
从集合导入defaultdict
pairs=defaultdict(列表)
对于i,枚举中的lst(数据):
对于k,在枚举中配对(zip(lst,lst[1:]):
pairs[pair]。追加((i,k))
#第二步:找到最常见的对和过滤器
most=最大值([len(lst)表示成对的lst.values()])
pairs={k:v代表k,v成对。如果len(v)=most}
打印(双)
# {(1, 2): [(0, 0), (1, 0), (2, 0)], (4, 5): [(0, 2), (1, 3), (2, 2)], (5, 6): [(0, 3), (1, 4), (2, 3)]}
#第三步:将配对扩展为三元组,将三元组扩展为四元组,等等。
三元组=[k+(数据[v[0][0]][v[0][1]+2],)
对于k,v成对。items()
如果len(v中(i,k)的(数据[i][k+2])==1]
打印(三份)
# [(4, 5, 6)]
假设一条“路径”必须包含至少两个元素,那么最常见的路径显然将包含两个元素(尽管也可能有一条路径包含两个以上的元素,它们同样常见,稍后将对此进行详细介绍)。因此,您可以迭代所有列表,计算每对连续数字在不同列表中出现的频率,并记住最常出现的那些数字对。这需要对每个列表迭代一次,这是在任何情况下都必须执行的最小数量

如果您对最长最常见的路径感兴趣,那么您可以以相同的方式开始,找到最常见的2段路径,但除了计数之外,还可以记录这些段的位置(例如,
{(3,4):[2,1,0],…}
在您的示例中,列表中的数字表示段在不同路径中的位置)。现在,您可以获取所有最常见的长度为2的路径,并查看是否对于其中任何一个路径,下一个元素对于该路径的所有引用也是相同的。在这种情况下,您有一个最常见的长度-3路径,它与前面的长度-2路径相同(显然,它不可能更常见)。您可以对length-4、length-5等重复此操作,直到无法在不使路径“不太常见”的情况下对其进行扩展。这一部分需要为每个扩展额外做n*k的工作,n是剩余的候选数量,k是这些候选数量出现的频率

(这假设频率拍长,即如果有一条长度为2的路径出现三次,则与长度为3的路径出现两次相比,您更喜欢这条路径。相同的方法也可用于不同的起始长度,例如,在不改变基本算法或复杂度的情况下,至少需要长度为3的路径。)


下面是一个用Python实现的简单示例来演示该算法。这只能扩展到长度-3,但可以通过循环轻松扩展到长度-4及更高。此外,它不会检查任何边缘情况(数组超出边界等)

#示例数据
数据=[[1,2,4,5,6,7,9],
[1,2,3,4,5,6,  8,9],
[1,2,  4,5,6,7,8  ]]
#第一步:计算每对出现的频率和位置
从集合导入defaultdict
pairs=defaultdict(列表)
对于i,枚举中的lst(数据):
对于k,在枚举中配对(zip(lst,lst[1:]):
pairs[pair]。追加((i,k))
#第二步:找到最常见的对和过滤器
most=最大值([len(lst)表示成对的lst.values()])
pairs={k:v代表k,v成对。如果len(v)=most}
打印(双)
# {(1, 2): [(0, 0), (1, 0), (2, 0)], (4, 5): [(0, 2), (1, 3), (2, 2)], (5, 6): [(0, 3), (1, 4), (2, 3)]}
#第三步:将配对扩展为三元组,将三元组扩展为四元组