【问题标题】:Permutation of the alphabet minimising the number of subsequences to construct a string字母表的排列最小化构建字符串的子序列数
【发布时间】:2021-04-27 13:26:07
【问题描述】:

您必须确定不同于“abcdefghijklmnopqrstuvwxyz”的特殊字母顺序。给你一个小写字符串,由字母“a”到“z”组成,最多 10000 个字符。您被要求确定重复这种特殊的字母顺序以生成给定字符串的最少次数。请注意,当您说出字母表时,您可以跳过某些字符(即,使用字母表的子序列)。

我的目标是有效地找到最佳的字母顺序,并计算产生给定字符串所需的重复次数。

示例:“cdadabcc”

答案:4

您得到 4,因为通过将字母表重新排序为:

cdabefghijklmnopqrstuvwxyz

第一次说字母表时,你说特殊排序的前三个字母“cdaefghijklmnopqrstuvwxyz”或“cda”,但跳过“b”和其余字符。下一次,你跳过说“c”和说“dab”,然后跳过剩下的字符。第三次,您说“c”并跳过剩余的字符。最后一次,您说“c”并跳过剩余的字符。

时间;特殊字母的一部分;总字符串

1; CDAbefghijklmnopqrstuvwxyz;光盘

2; cDABefghijklmnopqrstuvwxyz; cdadab

3; Cdabefghijklmnopqrstuvwxyz; cdadabc

4; Cdabefghijklmnopqrstuvwxyz; cdadabcc

示例 2:“abcdefdeff”

答案:3

将字母表改写为:

abcdefghijklmnopqrstuvwxyz

时间;特殊字母的一部分;总字符串

1; ABCDEFghijklmnopqrstuvwxyz; abcdef

2; abcDEFghijklmnopqrstuvwxyz; abcdefdef

3; abcdeFghijklmnopqrstuvwxyz; abcdefdeff

我该如何解决这个问题?如果我能确定字母表的特殊顺序,就很容易确定需要重复多少次才能生成字符串。为了确定这个顺序,我尝试使用动态规划并以类似于最长递增子序列问题的方式使用它。

【问题讨论】:

    标签: string algorithm optimization language-agnostic dynamic-programming


    【解决方案1】:

    让我们介绍几个术语:

    • 移动 - 输入中两个相邻的字母;
    • 跳跃 - 字母表允许的移动;
    • 重置 - 字母表不允许的移动;

    例如,如果字母是cba,输入是cbacaba

    • 移动将是:c->bb->aa->cc->aa->bb->a
    • 跳转将是:c->b, c->a & b->a;
    • 重置为:a->ca->b

    很容易看出答案是重置次数 + 1。因此我们只关心我们所做的移动是跳跃还是重置。

    这使我们能够简化输入 - 我们只关心移动(相邻字母对)。我们可以将输入压缩成一个二维矩阵,其中包含每个 Move 的数量:

    For cbacaba:
       a   b   c
    a  0   1   1  (a->b & a->c)
    b  2   0   0  (b->a x2)
    c  1   1   0  (c->a & c->b)
    

    现在我们可以注意到这个矩阵的一个有趣的属性。

    如果我们选择一个字母作为字母表的第一个字母,那么我们应该将该字母列的总和添加到答案中,因为对该字母的每次移动都会保证重置。此外,该字母行中的数字总和永远不会添加到答案中,因为所有这些移动都保证跳跃。 例如,如果我们将一个字母作为第一个:

    • a:+3 回答 (b->a x2 + c->a),-2 来自潜在答案。 (a->b & a->c)
    • b:+2 回答 (a->b + c->b),-2 来自潜在回答。 (a->b & c->b)
    • c:+1 回答(a->c),-2 潜在回答。 (c->a & c->b)

    现在我们可以选择最佳选项 - 显然是c,因为它从表中删除了 2 并且只在答案中添加了 1。在我们将字母放在字母表的第一位后,我们可以将问题视为好像没有那个字母一样。对于我们的 Moves 矩阵,这意味着我们只需删除相应的行和列。

    您可以重复此操作,一次增加一个字母,直到没有字母为止。通过Min(Sum(Column) - Sum(Row)) 挑选字母。在这种情况下:

       a   b   c
    a  0   1   x  (a->b)
    b  2   0   x  (b->a x2)
    c  x   x   x 
    

    这意味着将a作为下一个字母将添加2个Resets,并且仅添加一个b。显然,我们应该采用b,然后是a,这将给我们cba作为解决方案,重置的总数为:1(来自c)+ 1(来自b)+ 1(原始字母表) ) = 3。

    请注意,我没有测试过该解决方案,也无意测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      相关资源
      最近更新 更多