【问题标题】:Algorithm to find "ordered combinations"查找“有序组合”的算法
【发布时间】:2014-08-29 21:02:04
【问题描述】:

我需要一种算法来找到我所说的“有序组合”(如果有的话,也许有人知道它的真实名称)。 当然,我已经尝试过自己想出一个算法,但我真的卡住了。

它应该如何工作:

给定 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 才能成为有效结果。也许这有助于通过从较短的组合构建较长的组合来提高算法的性能。
  • 速度在这里非常重要。这是实时使用的算法!
  • 如果不清楚该算法的工作原理,请发表评论。我将添加一个示例来澄清它。
  • 也许这个问题已经知道并解决了,但我不知道它的正确名称。

【问题讨论】:

  • 我不是计算机科学家,但这感觉不是多项式的。WRWR WR WR WR WR WR WR 的简化版。
  • 对于ADSDASDD,难道ASD也可以吗?
  • @DavidEisenstat 是的,你当然是对的。我将编辑我的问题以包括 ASD。也可以添加!
  • 另外,我想SDFG 本身缺少DFG?肯定会吹毛求疵,因为我很确定我理解正确。
  • @DavidEisenstat 是的,这也是一个有效(和必需)的结果

标签: algorithm combinations


【解决方案1】:

我将此问题描述为枚举两个字符串的公共子序列。作为第一次切割,制作一个像这样的方法,它不确定地选择第一个字母并递归(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)

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

【讨论】:

  • “不确定地选择第一个字母”。不确定性和随机性一样吗?如果是这样,为什么不按 list1 的顺序遍历字母?
  • @Felheart Nondeterministically as in 遍历所有不同的可能性。
  • 您描述的答案非常有效。您能否详细说明建议的改进?不知道你说的表是什么意思?您是指以字母为键、索引数组为值的哈希表吗?我将如何使用它们?
  • @Felheart 我稍微扩展了描述。这个想法是提升线性时间集的交集并从枚举过程中找到操作。
  • @Felheart 我对数据结构有了更好的想法。剩下的是一个由word1 中的位置和word2 中的位置索引的二维数组,用于递归调用的可能参数列表。
猜你喜欢
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多