1. 程式人生 > >【LeetCode 中等題】3-最長迴文子串

【LeetCode 中等題】3-最長迴文子串

宣告:

今天是中等題第3道題。給定一個字串 s,找到 s 中最長的迴文子串。以下所有程式碼經過樓主驗證都能在LeetCode上執行成功,程式碼也是借鑑別人的,在文末會附上參考的部落格連結,如果侵犯了博主的相關權益,請聯絡我刪除

(手動比心ღ( ´・ᴗ・` ))

正文

題目:給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。

示例 1:

輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個有效答案。

示例 2:

輸入: "cbbd"
輸出:
"bb"

解法1。從頭開始遍歷每個元素看看是不是迴文串中心,對於每個元素,它有可能是迴文串的中心(奇數個字元),也有可能和它的下一個字元構成迴文串的中心(偶數個字元),由此判斷長度是不是更長來決定是否要更新起始index,程式碼如下。

執行用時: 932 ms, 在Longest Palindromic Substring的Python3提交中擊敗了66.74% 的使用者

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return
        len_s = len(s)
        for i in range(len_s):
            len1 = self.helper(s,i,i,len_s)    # 本身是迴文串中心的情況
            len2 = self.helper(s,i,i+1,len_s)  # 本身+下一個元素是迴文串中心的情況
            len_m = max(len1,len2)
            if len_m > end-start+1:    # 如果新的最長迴文串長度大於原來的就更新原迴文串始末index
                start = i - (len_m-1)//2
                end = i + len_m//2
        return s[start:end+1]


    # 該函式用於計算從當前元素左右擴充套件直到不是迴文串為止的index
    def helper(self,s,L,R,len_s):
        while L >= 0 and R < len_s and s[L] == s[R]:
            L -= 1
            R += 1
        return R - L - 1

                

解法2。還有種演算法Manacher,但我沒看太懂,而且下面的程式碼求的是最長迴文串長度,姑且看看,也許以後就懂了

def manacher(s):
    #預處理
    s='#'+'#'.join(s)+'#'

    RL=[0]*len(s)
    MaxRight=0
    pos=0
    MaxLen=0
    for i in range(len(s)):
        if i<MaxRight:
            RL[i]=min(RL[2*pos-i], MaxRight-i)
        else:
            RL[i]=1
        #嘗試擴充套件,注意處理邊界
        while i-RL[i]>=0 and i+RL[i]<len(s) and s[i-RL[i]]==s[i+RL[i]]:
            RL[i]+=1
        #更新MaxRight,pos
        if RL[i]+i-1>MaxRight:
            MaxRight=RL[i]+i-1
            pos=i
        #更新最長迴文串的長度
        MaxLen=max(MaxLen, RL[i])
    return MaxLen-1



# V 2.0
# manacher演算法
def manacher(self):
        s = '#' + '#'.join(self.string) + '#'               # 字串處理,用特殊字元隔離字串,方便處理偶數子串
        lens = len(s)
        f = []                                          # 輔助列表:f[i]表示i作中心的最長迴文子串的長度
        maxj = 0                                        # 記錄對i右邊影響最大的字元位置j
        maxl = 0                                        # 記錄j影響範圍的右邊界
        maxd = 0                                        # 記錄最長的迴文子串長度
        for i in range(lens):                           # 遍歷字串
            if maxl > i:
                count = min(maxl-i, int(f[2*maxj-i]/2)+1)  # 這裡為了方便後續計算使用count,其表示當前字元到其影響範圍的右邊界的距離
            else :
                count = 1
            while i-count >= 0 and i+count < lens and s[i-count] == s[i+count]:  # 兩邊擴充套件
                count += 1
            if(i-1+count) > maxl:                         # 更新影響範圍最大的字元j及其右邊界
                maxl, maxj = i-1+count, i
            f.append(count*2-1)
            maxd = max(maxd, f[i])                       # 更新迴文子串最長長度
        return int((maxd+1)/2)-1                        # 去除特殊字元

結尾

解法1:官方解法

解法2:https://segmentfault.com/a/1190000003914228   https://blog.csdn.net/asd136912/article/details/78987624