String 字母表的排列尽量减少子序列的数量以构造字符串

String 字母表的排列尽量减少子序列的数量以构造字符串,string,algorithm,optimization,language-agnostic,dynamic-programming,String,Algorithm,Optimization,Language Agnostic,Dynamic Programming,字母表的特殊顺序不同于“abcdefghijklmnopqrstuvwxyz”,您必须确定。您将收到一个小写字符串,其中包含字母“a”到“z”,最长为10000个字符。您需要确定重复字母表这种特殊顺序以生成给定字符串的最小次数。请注意,当您说出字母表时,可以跳过一些字符(即,使用字母表的子序列) 我的目标是有效地找到字母表的最佳顺序,并计算生成给定字符串所需的重复次数 示例:“CDADABC” 答复:4 您得到4,因为将字母表重新排序为: CDABEFGHIJKLMNOPQRSTUVXYZ 第一

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

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

示例:“CDADABC”

答复:4

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

CDABEFGHIJKLMNOPQRSTUVXYZ

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

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

一,;CDAbefghijklmnopqrstuvwxyz;cda

二,;cDABefghijklmnopqrstuvwxyz;cdadab

三,;Cdabefghijklmnopqrstuvwxyz;cdadabc

四,;Cdabefghijklmnopqrstuvwxyz;cdadabcc

示例2:“abcdefdeff”

答复:3

将字母表改写为:

abcdefghijklmnopqrstuvwxyz

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

一,;ABCDEFghijklmnopqrstuvwxyz;abcdef

二,;abcDEFghijklmnopqrstuvwxyz;abcdefdef

三,;abcdeFghijklmnopqrstuvwxyz;abcdefdeff


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

让我们介绍几个术语:

  • 移动-输入中的两个相邻字母
  • 跳跃-字母表允许的移动
  • 重置-字母表不允许的移动
例如,如果字母表为
cba
,输入为
cbacaba

  • 移动将是:
    c->b
    b->a
    a->c
    c->a
    a->b
    b->a
  • 跳转将是:
    c->b
    c->a
    &
    b->a
  • 重置为:
    a->c
    a->b
很容易看出,答案是重置次数+1。因此,我们所关心的是我们所做的动作是跳跃还是重置

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

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个选项。在我们把字母放在字母表的第一位之后,我们可以把这个问题当作根本没有这个字母一样来处理。对于我们的移动矩阵,这意味着我们只需删除相应的行和列

你可以重复这个过程,一次增加一个字母,直到没有字母剩下。按
Min(总和(列)-总和(行))
拾取字母。在这种情况下:

   a   b   c
a  0   1   x  (a->b)
b  2   0   x  (b->a x2)
c  x   x   x 
这意味着将
a
作为下一个字母将添加2次重置,而只添加
b
一次重置。显然,我们应该先选择
b
,然后选择
a
,这将为我们提供
cba
作为解决方案,重置总数为:1(从
c
)+1(从
b
)+1(原始字母)=3

请注意,我还没有测试解决方案,也不打算测试