字母表的排列,最大限度地减少了构建字符串的子序列的数量

Permutation of the alphabet minimising the number of subsequences to construct a string

提问人:cracra 提问时间:1/23/2021 最后编辑:גלעד ברקןcracra 更新时间:1/24/2021 访问量:431

问:

字母表有一个特殊的顺序,与“abcdefghijklmnopqrstuvwxyz”不同,您必须确定。您将获得一个包含字母“a”到“z”的小写字符串,长度最多为 10000 个字符。系统要求您确定可以重复这种特殊字母顺序以生成给定字符串的最小次数。请注意,当您说出字母表时,您可以跳过一些字符(即使用字母表的子序列)。

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

示例: “cdadabcc”

答案:4

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

cdabefghijklmnopqrstuvwxyz

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

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

1;CDAbefghijklmnopqrstuvwxyz;CDA(CDA)

2;cDABefghijklmnopqrstuvwxyz;CDADAB公司

3;Cdabefghijklmnopqrstuvwxyz;CDADABC (英语)

4;Cdabefghijklmnopqrstuvwxyz;CDADABCC

示例 2:“abcdefdeff”

答案:3

将字母表改写为:

abcdefghijklmnopqrstuvwxyz

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

1;ABCDEFghijklmnopqrstuvwxyz;abcdef的

2;abcDEFghijklmnopqrstuvwxyz;abcdefdef的

3;abcdeFghijklmnopqrstuvwxyz;abcdefdeff(阿布德夫夫)

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

字符串 算法 优化 与语言无关的动态 规划

评论


答:

0赞 user3707125 1/24/2021 #1

让我们介绍几个术语:

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

例如,如果 alphabet is 和 input 是:cbacbacaba

  • 移动将是:、、、、、c->bb->aa->cc->aa->bb->a;
  • 跳跃将是: ,c->bc->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)

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

您可以重复此操作,一次增加一个字母,直到没有字母为止。按 挑选字母。在这种情况下: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 

这意味着作为下一个字母将添加 2 个重置,并且只添加一个。显然,我们应该采取,然后这将给我们一个解决方案,重置的总数为:1(从)+ 1(从)+ 1(原始字母)= 3。abbacbacb

请注意,我尚未测试该解决方案,也无意测试。