這是leetcode上的一道算法題python
對的就是這道題,,困擾了我整整一上午,, 一直也沒考慮用動態規劃作,, 最終用動態規劃把他解決了!算法
迴文串: 正過來和倒過來長的同樣, 好比 理總理, 席主席。。。數組
思想是這樣的:spa
用 dp[i][j] 表示 字符串s的子串s[i:j] 是否是迴文串 0表示不是 1表示是code
當 i == j 的時候 dp[i][j] 都是1 blog
(意思是s[1:1] s[2:2] 就是一個字符, 字符本身算是個迴文子串)leetcode
當 i == j-1 的時候,若是 s[i] == s[j] 那dp[i][j] =1 不然爲0 字符串
(倆字符,這倆是同樣的就是迴文字符 不然就不是)io
其餘狀況,當 i < j-1 的時候, class
若是 dp[i+1][j-1]==1 而且 s[i] == s[j] 的時候 dp[i][i] 就是1
(s[j] 和 s[j] 中間 不包含他倆,原來就是迴文的, 他倆仍是一個字符,, 那算上這倆也是迴文)
不然 dp[i][j] 都是0
(1 s[i]和s[j]中間不包含他倆, 原來不是迴文,,那算上他倆也不是迴文。
2 若是他倆中間原本是迴文 他倆不是一個字符,那算上他倆以後就不是迴文)
這樣的方式 初始化二維數組, 先把對角線填充上, 而後再把 對角線上一層(兩個相鄰元素是否相等) 填充上,
而後斜着一層一層填充表就能夠。
爲了不從新查表獲得最長子串, 能夠在填充過程,記錄當前最長的子串長度,起始index和結束index
把個人草紙拍下來,你們別嫌棄醜, 填表順序記錄下來 但願對你們有幫助:
個人python代碼:
1 class Solution: 2 def longestPalindrome(self, s): 3 """ 4 :type s: str 5 :rtype: str 6 """ 7 length = len(s) # 字符串長度 8 max_length = 1 # 動態規劃過程當中記錄最長迴文串長度 默認1是一個字符的狀況 9 start = 0 # 最長迴文子串的開始位置 默認一開始s[0]本身是一個迴文子串 10 end = 0 # 迴文子串的階數位置 11 # 初始化一個 s長度的二維數組 記錄dp過程 12 record = [[0 for i in range(length)] for _ in range(length)] 13 # record[i][j] 表明 s[i:j] 是否是迴文子串 14 for i in range(length): 15 # 對角線全填充1 表明 一個字符是迴文子串 16 record[i][i] = 1 17 # 相鄰兩個字符若是相同 就記錄1 不然記錄0 18 if i >= 1: 19 if s[i] == s[i-1]: 20 record[i-1][i] = 1 21 max_length = 2 22 start = i-1 23 end = i 24 else: 25 record[i-1][i] = 0 26 # 前面兩步驟把i j 相差0 和相差1 的狀況都在表裏填充上了 27 # 下面 改用left看成起始位置 right看成結束位置i和j 28 # 用i表明left和start的間隔 從2開始到length-1爲止 29 # 用j從1到length-i 30 # 下面開始填充斜對角線 31 for i in range(2, length): 32 for j in range(length - i): 33 left = j 34 right = j + i 35 # 若是 s[left+1: right-1] 是迴文串 而且 這兩個位置字符相同 則s[left:right]也是迴文的 不然不是 36 if record[left+1][right-1] == 1 and s[left] == s[right]: 37 record[left][right] = 1 38 # 若是發現當前迴文串比以前發現的長度長 則更新長度 開始位置和結束位置 39 if right - left + 1 > max_length: 40 start = left 41 end = right 42 max_length = right - left + 1 43 else: 44 record[left][right] = 0 45 # 返回發現的最長迴文串 46 return s[start: end+1] 47 48 49 if __name__ == '__main__': 50 s = Solution() 51 res = s.longestPalindrome("abbajlhkh") 52 print(res)