在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) ''
[]