【LeetCode之動態規劃】5-最長迴文字符串

最長迴文字符串

方法一:暴力匹配 (Brute Force)
1、根據迴文子串的定義,枚舉所有長度大於等於 22 的子串,依次判斷它們是否是迴文;
2、在具體實現時,可以只針對大於“當前得到的最長迴文子串長度”的子串進行“迴文驗證”;
3、在記錄最長迴文子串的時候,可以只記錄“當前子串的起始位置”和“子串長度”,不必做截取。這一步我們放在後面的方法中實現。

class Solution:
    def longestPalindrome(self, s):
        res = []
        for i in range(len(s)):
            for j in range(i+1,len(s)+1):
                if s[i:j] == s[i:j][::-1]:
                    res.append(s[i:j])
                else:
                    continue
        print(res)
        return max(res,key=len)   #學習這種直接返回列表長度最長的字符串方法

方法二:動態規劃
在這裏插入圖片描述
依然從迴文串的定義展開討論:

1、如果一個字符串的頭尾兩個字符都不相等,那麼這個字符串一定不是迴文串;

2、如果一個字符串的頭尾兩個字符相等,纔有必要繼續判斷下去。

(1)如果裏面的子串是迴文,整體就是迴文串;

(2)如果裏面的子串不是迴文串,整體就不是迴文串。

即在頭尾字符相等的情況下,裏面子串的迴文性質據定了整個子串的迴文性質,這就是狀態轉移。因此可以把“狀態”定義爲原字符串的一個子串是否爲迴文子串。

第 1 步:定義狀態

dp[i][j] 表示子串 s[i, j] 是否爲迴文子串。

第 2 步:思考狀態轉移方程
這一步在做分類討論(根據頭尾字符是否相等),根據上面的分析得到:

dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]

第 3 步:考慮初始化
初始化的時候,單個字符一定是迴文串,因此把對角線先初始化爲 1,即 dp[i][i] = 1 。

第 4 步:考慮輸出
只要一得到 dp[i][j] = true,就記錄子串的長度和起始位置,沒有必要截取,因爲截取字符串也要消耗性能,記錄此時的迴文子串的“起始位置”和“迴文長度”即可。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        if size < 2:
            return s

        dp = [[False for _ in range(size)] for _ in range(size)]

        max_len = 1
        start = 0

        for i in range(size):
            dp[i][i] = True

        for j in range(1, size):
            for i in range(0, j):
                if s[i] == s[j]:
                    if j - i < 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i + 1][j - 1]
                else:
                    dp[i][j] = False

                if dp[i][j]:
                    cur_len = j - i + 1
                    if cur_len > max_len:
                        max_len = cur_len
                        start = i
        return s[start:start + max_len]
class Solution2:
    def longestPalindrome(self, s):
        if not s:
            return ""

        s_len = len(s)
        mem = [[0] * s_len for _ in range(s_len)]
        left, right, result_len = 0, 0, 0

        for j in range(s_len):
            for i in range(0,j):
                if s[i] == s[j] and (j - i < 2 or mem[i + 1][j - 1]):   # if 0 or other -->(0爲False)
                    mem[i][j] = 1
                if mem[i][j] and result_len < j - i + 1:
                    result_len = j - i + 1
                    left, right = i, j
            mem[j][j] = 1
            print(mem)
        return s[left:right + 1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章