在Python中查找最大长度N的最长重复子序列

在Python中查找最大长度N的最长重复子序列,python,combinations,subsequence,Python,Combinations,Subsequence,我有一些表示事件顺序的字符串: s1='A->B->E->D->A->C->B->D' s2='A->B->C->A->B' s3='A->B->A 在每个字符串中,我想找到最大长度为N的所有重复模式 import itertools def find_all_comb(event_list,max_events): all_combs = [] for j in range(1,max_events+1): all_combs.extend(list(set(

我有一些表示事件顺序的字符串:

s1='A->B->E->D->A->C->B->D'

s2='A->B->C->A->B'

s3='A->B->A

在每个字符串中,我想找到最大长度为N的所有重复模式

import itertools

def find_all_comb(event_list,max_events):
    all_combs = []
    for j in range(1,max_events+1):
        all_combs.extend(list(set(['->'.join(x) for x in list(itertools.combinations(event_list,j))])))
    return all_combs

def find_repeating_patterns(x):
    split_events = x.split("->")
    all_combs = find_all_comb(split_events,int(len(x)/2))

    repeating_patterns = []
    for comb in all_combs:
        c_split_event = [p for p in split_events if p in comb]
        if '->'.join(c_split_event).count(comb) > 1:
            repeating_patterns.extend([comb])
    output_list = []
    longest_repeating_patterns = [s for s in repeating_patterns if any(set(s).issuperset(set(i)) and len(s) > len(i) for i in repeating_patterns)]
    while output_list != longest_repeating_patterns:
        if longest_repeating_patterns == []:
            break
        output_list = longest_repeating_patterns.copy()
        longest_repeating_patterns = [s for s in longest_repeating_patterns if any(set(s).issuperset(set(i)) and len(s) > len(i) for i in longest_repeating_patterns)]

return output_list
对于
s1
,它返回正确的模式
[A,B,D]
,对于
s2
,它返回
[A,B]
。对于
s3
,它应该返回
[A]
,但它返回一个空列表。这是因为:

[s for s in repeating_patterns if any(set(s).issuperset(set(i)) and len(s) > len(i) for i in repeating_patterns)]
它不允许
len(s)>len(i)


如何在这里捕获这两种情况?

添加一条额外的行,将任何不是子序列的内容添加到
输出列表中的任何序列中,这是一种解决方案

    import itertools

    def find_all_comb(event_list,max_events):
        all_combs = []
        for j in range(1,max_events+1):
            all_combs.extend(list(set(['->'.join(x) for x in list(itertools.combinations(event_list,j))])))
        return all_combs

    def find_repeating_patterns(x):
        split_events = x.split("->")
        all_combs = find_all_comb(split_events,int(len(x)/2))
        
        repeating_patterns = []
        for comb in all_combs:

            c_split_event = [p for p in split_events if p in comb]
            if '->'.join(c_split_event).count(comb) > 1:
                repeating_patterns.extend([comb])
        output_list = []
        longest_repeating_patterns = [s for s in repeating_patterns if any(set(s).issuperset(set(i)) and len(s) > len(i) for i in repeating_patterns)]
        while output_list != longest_repeating_patterns:
            if longest_repeating_patterns == []:
                break
            output_list = longest_repeating_patterns.copy()
            longest_repeating_patterns = [s for s in longest_repeating_patterns if any(set(s).issuperset(set(i)) and len(s) > len(i) for i in longest_repeating_patterns)]
        output_list.extend([s for s in repeating_patterns if not any(set(i).issuperset(set(s)) for i in output_list)]) <--- ADDED LINE FOR SOLUTION

        return output_list


s1 = A->B->E->D->A->C->B->D
s2 = A->B->C->A->B
s3 = A->B->A

print(find_repeating_patterns(s1))

output: [A->B->D]

print(find_repeating_patterns(s2))

output: [A->B]

print(find_repeating_patterns(s3))

output: [A]
导入itertools
def find_all_comb(事件列表、最大事件):
所有梳子=[]
对于范围内的j(1,最大事件+1):
所有组合扩展(list(set(['->'.join(x)表示列表中的x(itertools.compositions(event_list,j)))))
归还所有梳子
def查找重复模式(x):
拆分事件=x.split(“->”)
all_combs=查找_all_comb(拆分事件,int(len(x)/2))
重复_模式=[]
对于所有梳子中的梳子:
c_split_event=[p表示split_events中的p,如果comb中的p为p]
如果'->'。加入(c_分割事件)。计数(梳)>1:
重复_模式。扩展([comb])
输出列表=[]
最长的重复模式=[s代表重复模式中的s(如果有)(集合)。issuperset(集合(i))和len(s)>len(i)代表重复模式中的i)]
当输出_列表时!=最长的\u重复\u模式:
如果最长的\u重复\u模式=[]:
打破
输出\列表=最长\重复\模式。复制()
最长的重复模式=[s代表最长的重复模式中的s,如果有的话(set(s).issuperte(set(i))和len(s)>len(i)代表最长的重复模式中的i)]
输出列表。扩展([s代表重复模式中的s,如果没有(设置(i)。issuperset(设置(s))代表输出列表中的i)])B->E->D->A->C->B->D
s2=A->B->C->A->B
s3=A->B->A
打印(查找重复模式(s1))
输出:[A->B->D]
打印(查找重复模式(s2))
输出:[A->B]
打印(查找重复模式(s3))
产出:[A]

以下是一个更简单、更高效的解决方案:

def longest_subsequence(events, limit, sep='->'):
    events = list(enumerate(events.split(sep)))
    output = {}
    seen = {}
    for n in range(limit, 0, -1):
        for combination in itertools.combinations(events, n):
            indexes, key = zip(*combination)
            if key in seen:
                if key not in output and seen[key].isdisjoint(indexes):
                    output[key] = sep.join(key)
            else:
                seen[key] = set(indexes)
        if output:
            break
    return list(output.values())
这将首先查看最长的匹配,如果找到,则会提前终止。它通过保存最后匹配的索引并将其与当前候选项进行比较,消除了自重叠重复子序列

演示:

输出:

(1) 'A->B->E->D->A->C->B->D'
['A->B->D']

(2) 'A->B->C->A->B'
['A->B']

(3) 'A->B->A'
['A']

(4) 'A->B->E->D->A->C->B->E->D->A'
['A->B->E->D', 'B->E->D->A']

(5) 'B->B->B->C->C'
['B->C']

(6) 'A->B->A->B->C->C'
['A->B->C']

(7) 'A'
[]

(8) ''
[]

要求似乎不明确,因为
[A,B,D]
是一个子集而不是子序列。同样,您的代码不会忽略顺序,因此它也不是一个简单的子集。@ekhumaro
[a,B,D]
是一个序列。在标题中添加了“repeating”一词,希望这能澄清问题。我在文章的最后一行还有一个更简洁的要求,也应该澄清问题。这真的是关于集合和序列的吗?不清楚如何。对于
A->B->E->D->A->C->B->E->D->A
,应该输出什么?您当前的解决方案提供了
['B->E->D->A',A->B->E->D']
,其中包括一些重叠的子序列,但不是全部。如果包括所有的可能性,那么
s1
的正确输出将是
['A->B->E->D',A->C->B->D']
(因为
ABE
CBD
可以使用两次)。嗨,约束条件是一个事件不能在两种模式中使用。不确定您是否仍然感兴趣,但我有一个更简单、更有效的解决方案,可以产生与您相同的输出。请分享,我肯定仍然感兴趣。好的-我现在添加了我的替代解决方案。嗨,当输入'a->B->a->B->C'时,它只输出['a->B']。所以有些东西没有按预期工作。@kspr好的-这很容易改变(请参阅我更新的答案)。这就是为什么我要求您澄清应该如何处理重叠的子序列。您并没有真正这样做,所以我只是添加了
B->B->B->C->C
示例,并使我的输出与您的匹配。请注意,对于样本5和样本6,您当前的解决方案因此被破坏(如上输出中的编号)。
(1) 'A->B->E->D->A->C->B->D'
['A->B->D']

(2) 'A->B->C->A->B'
['A->B']

(3) 'A->B->A'
['A']

(4) 'A->B->E->D->A->C->B->E->D->A'
['A->B->E->D', 'B->E->D->A']

(5) 'B->B->B->C->C'
['B->C']

(6) 'A->B->A->B->C->C'
['A->B->C']

(7) 'A'
[]

(8) ''
[]