找到要添加到字符串中的最小字符数,使其成为回文

时间:2015-12-14 19:38:48

标签: algorithm dynamic-programming

这是一个来自spoj的问题。 AIBOHP

字符可以添加到字符串中的任何位置 我读到的最简单的解决方案如下:
找到字符串的最长公共子序列,它是相反的。那么答案是(字符串的长度 - 两个字符串的LCS)。这种看起来很直观,但我很难证明这一点。如果这个问题看起来很愚蠢,我很抱歉,有人可以清楚地解释为什么这种方法总能奏效。

注意:Stack Overflow上有时会询问与此问题相关的问题,但这些问题似乎都没有回答我的问题。 这个问题并不重复,在this问题中,一个答案说明了这种方法,但没有给出直觉或证据,这正是我所要求的。我知道如何解决它,我问为什么这个方法有效。

2 个答案:

答案 0 :(得分:2)

让我们意识到你的LCS只不过是原始输入的最长子回文(不必连续)。如果x是最长子回文中包含的的字母数,您可以轻松地将2x添加到该子回文以使其包含您的原始输入并保持回文。

berries一词写成bERRiEs,标记最长子回文的大写字母为ERRE。从中间开始,为原始单词中的每个小写字母添加2个字母:ERRE -> EiRRiE -> bEiRRiEb -> sbEiRRiEbs然后就可以了。

另一方面,这无法改善。考虑您已将y个字符添加到输入中以使其成为回文。删除2y个字符(添加的字符及其镜像)以获得输入序列的子回文 - 这显然不能大于最长的子回文,因此您至少添加了缺少字符的数量。最长的副回文。

答案 1 :(得分:1)

您可以使用以下算法使用n个插入将字符串更改为回文结构,其中n是字符串长度与其LCS长度之间的差异:

  1. 查找字符串的LCS及其反向。将LCS的字符放入堆栈lcs
  2. palindrome设置为原始字符串
  3. s设置为空字符串。将i设为0。
  4. 沿着反向弦走。对于反向字符串中的每个字符c
    1. 如果lcs的顶部与c匹配:
      1. Pop lcs
      2. s字符
      3. 之后将palindrome插入i
      4. s设置为空字符串
      5. i设置为原始字符串c
      6. 中的位置
    2. 否则,将c追加到s
  5. 由于反向字符串中的字符仅添加到s,随后进入最终的回文,如果它不在LCS中,则插入的字符总数是反向字符串的长度减去LCS的长度。

    这是一个例子。给定字符串thisisatest,反之为字符串tsetasisiht。 LCS是t-isi-t

          t h  isi sates t
    ^ tse t as isi h     t
          _    ___       _
    =     t    isi       t
    

    反向字符串的“缺失”子序列为tseash

      tse t as isi h t
    -     t    isi   t
      ___   __     _
    = tse   as     h
    

    请注意,这些缺失子序列中的字符总数是原始字符串的长度减去LCS的长度,表明您感兴趣的声明。

    在字符串开头后插入tseas之后th之后插入isi,如下所示:

          t   h  isi  sates t
    + tse   as       h      
      ___ _ ___  ___ ______ _
    = tse t ash  isi hsates t
    

    我们获得了回文tsetashisihsatest