用于查找"有序组合的算法"

时间:2014-08-29 21:02:05

标签: algorithm combinations

我需要一个算法来查找,我称之为"有序组合" (如果有的话,也许有人知道这个的真实姓名)。 当然我已经尝试过自己想出一个算法,但我真的卡住了。

它应该如何运作:

给出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

说明:

  • 虽然它是一种与语言无关的算法,但我更喜欢包含C#或伪代码的答案,所以我可以理解它们。
  • 我意识到较长的组合总是由较短的组合组成。示例:如果SD和DF也可以,SDF只能是有效的结果。也许这有助于通过构建较短的组合来使算法更高效。
  • 速度在这里非常重要。这个算法将实时使用!
  • 如果不清楚算法是如何工作的,请删除评论。我将添加一个示例来澄清它。
  • 也许这个问题已经知道并解决了,但我不知道它的正确名称。

1 个答案:

答案 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)

这个多项式时间预处理步骤将枚举速度提高到渐近最优。