求字符串的最長回文子串(動態(tài)規(guī)劃)

問題

給定一個字符串 S,找出其最長的回文子字符串。S 的最大長度為1000。

舉例

輸入:"babad"

輸出:"bab"
(注:"aba" 也是一個正確的結果)

思路

若長度為 L 的字符串為回文,則去掉首尾的字符,長度為 L-2 的字符串也為回文。
即全局最優(yōu)解包含局部最優(yōu)解。

最小子問題

  1. 單個字符獨立成為一個回文字符串
  2. 相鄰的兩個相同字符,是一個回文字符串

遞推方程

設置一個 L*L 的矩陣 D,D[i][j] 的值為 ture 或 false, 表示從 i 起始 j 終止的字符串是否為回文。
則有:

D[i][j] = (D[i] === D[j]) && D[i+1][j-1]
(若第 i 個字符與第 j 個字符相同,且從 i+1 起始 j-1 終止的字符串為回文,則有從 i 起始 j 終止的字符串也為回文)

解法

function handleStr(str) {
  let L = str.length
  let d = []
  for(let i=0;i<L;i++) { // 初始化矩陣D,且先將最小子問題1的情況都設置為true
    let arr = []
    arr[i] = true
    d[i] = arr
  }
  
  let maxLen = 1,
      resIndex = 0
  
  for(let i=0;i<L;i++) { // 再將最小子問題2的情況都設置為true
    if(str[i] === str[i+1]) {
      d[i][i+1] = true
      if(maxLen < 2) { // 如果最小子問題成立,則最長回文字符串為2
        maxLen = 2
        resIndex = i
      }
    }
  }
  
  
  for(let len=3;len<=L;len++) { // 從長度為3開始逐漸增長的檢查回文字符串
    for(let i=0;i<L-len+1;i++) { // 從第0個位置開始,依據(jù)最小子問題1、2來依次檢查回文字符串
      if(str[i] === str[i+len-1] && d[i+1][i+len-2]) {
        d[i][i+len-1] = true
        if(len > maxLen) { // 滿足條件時,保存回文字符串長度和起始位置
          maxLen = len
          resIndex = i
        }
      }
    }
  }
  
  return str.substr(resIndex, maxLen)
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容