我需要一个算法来查找,我称之为"有序组合" (如果有的话,也许有人知道这个的真实姓名)。 当然我已经尝试过自己想出一个算法,但我真的卡住了。
给出2个列表(不是集合,这里的顺序很重要!),保证包含相同元素的元素,所有有序组合。 有序组合是在两个列表中相同顺序中出现的元素的2元组,3元组,... n元组(无N限制)。
我不确定这是否清楚,所以这里有多个例子: (List1,List2,预期结果,注释)
ASDF
ADSF
Result: AS, AD, AF, SF, DF, ASF, ADF
注意:ASD不是有效结果,因为此组合的第二个列表中无法有升序索引
ADSD
ASDD
Result: AD, AS, AD, DD, SD, ASD, ADD
注意:AD出现两次,因为它可以从索引1,2和1,4以及第二个列表1,3和1,4中创建。但如果它只出现一次也是正确的。此外,D在两个列表中按顺序出现两次,因此这也允许ADD作为有效组合。
SDFG
SDFG
Result: SD, SF, SG, DF, DG, FG, SDF, SFG, SDG, DFG, SDFG,
注意:相同的输入;所有组合都是可能的
ABCDEFG
GFEDCBA
Result: <empty>
注意:两个列表中没有相同顺序的组合
QWRRRRRRR
WRQ
Result: WR
注意:两个集合中以相同顺序出现的唯一组合是WR
答案 0 :(得分:2)
我会将此问题描述为枚举两个字符串的常见子序列。作为第一个剪辑,制作一个这样的方法,它选择不确定的第一个字母和recurses(Python,对不起)。
def commonsubseqs(word1, word2, prefix=''):
if len(prefix) >= 2:
print(prefix)
for letter in set(word1) & set(word2): # set intersection
# figure out what's left after consuming the first instance of letter
remainder1 = word1[word1.index(letter) + 1:]
remainder2 = word2[word2.index(letter) + 1:]
# take letter and recurse
commonsubseqs(remainder1, remainder2, prefix + letter)
如果这个简单的解决方案不够快,那么它可以改进如下。对于这两个单词的每对后缀,我们预先计算递归调用的列表。再次在Python中:
def commonsubseqshelper(table, prefix, i, j):
if len(prefix) >= 2:
print(''.join(prefix))
for (letter, i1, j1) in table[i][j]:
prefix.append(letter)
commonsubseqshelper(table, prefix, i1, j1)
del prefix[-1] # delete the last item
def commonsubseqs(word1, word2):
table = [[[(letter, word1.index(letter, i) + 1, word2.index(letter, j) + 1)
for letter in set(word1[i:]) & set(word2[j:])]
for j in range(len(word2) + 1)] # 0..len(word2)
for i in range(len(word1) + 1)] # 0..len(word1)
commonsubseqshelper(table, [], 0, 0)
这个多项式时间预处理步骤将枚举速度提高到渐近最优。