将插入次数最少的字符串转换为回文

时间:2019-03-15 08:47:01

标签: string algorithm dynamic-programming palindrome

这是来自https://www.dailycodingproblem.com/的问题:

  

给出一个字符串,找到可以通过插入   单词中尽可能少的字符数。如果有   超过一个可以形成的最小长度的回文   在字典上最早的(按字母顺序排列的第一个)。

     

例如,给定字符串“ race”,您应该返回“ ecarace”,   因为我们可以在其中添加三个字母(这是   做回文)。还有其他七种回文   从“种族”中添加三个字母,但“ ecarace”排在第一位   按字母顺序。

     

作为另一个示例,给定字符串“ google”,您应该返回   “ elgoogle”。

它类似于this SO问题或this GeeksforGeeks帖子。相似,但不相同;他们都没有提供任何有关复发的解释,就好像他们是凭空抽出了溶液,而且他们也没有重建溶液,更不用说按字典顺序最早的溶液了。

经过一番思考,我的理解如下:

  

对于任何字符串s[i..j],请注意,如果s[i] == s[j],则   使其回文所需的插入次数与   使s[i+1..j-1]回文所需的插入次数。

     

但是,如果s[i] != s[j]可以将s[i..j-1]转换为   回文,然后在开头插入s[j],或进行转换   s[i+1..j]返回回文,并在末尾插入s[i]。既然我们是   在寻找最少插入次数的情况下,我们将选择   至少两个选项。插入次数多于   所选子问题所需的插入次数(对于   在开头或结尾添加一个字符。

我如何重建词典上最早的解决方案?

2 个答案:

答案 0 :(得分:2)

首先,让我们回答“如何重建解决方案”,然后集中精力订购。假设您将插入次数存储在2D矩阵insertions[start][stop]中,则只需回溯您的步骤,即可“收集”插入的字符。我们需要一个新的数组来存储输出字符串,其长度等于我们的起始字符串加上最少的插入次数。我们还将存储两个索引,指向从正面到阵列的下一个可用点。

首先比较当前子字符串的第一个和最后一个字母,如果相等,则将输出字符串都分配给这两个字符串,分别位于前面和后面的下一个可用位置。例如,如果我们有FYRF作为当前子字符串,我们将分配输出字符串F..F,其中.是不确定的字符。然后我们的子字符串变为s[i+1..j-1]YR

如果两个字符不匹配,我们将比较insertions[i+1][j]insertions[i][j-1]中的记录,看哪个更小(至少其中一个比{{1 }})。如果它们相等,则选择一个(我们将在稍后返回)。在输出字符串中分配与我们复制/插入的子字符串的字母相对应的字符,在输出字符串的下一个可用的前后索引处。也就是说,在insertions[i][j]的情况下,如果我们决定为JLL添加一个J,我们将使用子字符串JLLJ,因此我们将存储{{1 }}和s[i+1..j]放在输出字符串J中。如果我们的输出字符串已经包含J,那么我们将存储J..J。我们重复整个过程,直到分配了所有字符。

现在,按照字典顺序进行排序。对于上一段中AR....RAARJ..JRA相等的情况,我们不应该随机选择其中之一。相反,我们应该按字典顺序比较insertions[i+1][j]insertions[i][j-1],如果s[i]首先出现,则将s[i+1]插入输出字符串/继续进行s[i]。否则,请使用s[i] / insertions[i+1][j]。这将为我们提供所有可用选项中按词典顺序排列的最快字符串。

答案 1 :(得分:1)

这里的OP:@ dillon-davis的答案是正确的(被否决),尽管那时我自己已经知道了。我已经在问题中提供了基本算法的说明,@ dillon-davis提供了重构的说明,为完整起见,这是Scala中的工作代码。

list1=['student1',10,20,40,'student2',20,20,40,'student3',20,30,40,'student4',20,10,30]
list2=[]
for i in range(0, len(list1), 4):
    list2.append(list1[i])
    sum = list1[i+1]+list1[i+2]+list1[i+3]
    list2.append(sum)
print(list2)