leetcode 求乙個字串的最長回文子串

2022-06-07 18:30:09 字數 3593 閱讀 8999

最長回文子串問題:給定乙個字串,求它的最長回文子串長度。如果乙個字串正著讀和反著讀是一樣的,那它就是回文串。

給定乙個字串,求它最長的回文子串長度,例如輸入字串'35534321',它的最長回文子串是'3553',所以返回 4。

最容易想到的辦法是列舉出所有的子串,然後一一判斷是否為回文串,返回最長的回文子串長度。不用我說,列舉實現的耗時是我們無法忍受的。那麼有沒有高效查詢回文子串的方法呢?答案當然是肯定的,那就是中心擴充套件法,選擇乙個元素作為中心,然後向外發散的尋找以該元素為圓心的最大回文子串。但是又出現了新的問題,回文子串的長度即可能是奇數,也可能好是偶數,對於長度為偶數的回文子串來說是不存在中心元素的。那是否有一種辦法能將奇偶長度的子串歸為一類,統一使用中心擴充套件法呢?它就是manacher演算法,在原字串中插入特殊字元,例如插入 #後原字串變成'#3#5#5#3#4#3#2#1#'。現在我們對新字串使用中心擴充套件發即可,中心擴充套件法得到的半徑就是子串的長度。

現在實現思路已經明確了,先轉化字串'35534321'  ---->  '#3#5#5#3#4#3#2#1#',然後求出以每個元素為中心的最長回文子串的長度。以下給出 python 實現:

#!/usr/bin/python

# -*- coding: utf-8 -*-def max_substr(

string

): s_list = [s for s in

string]

string = '

#' + '

#'.join(s_list) + '#'

max_length = 0

length = len(string)

for index in range(0

, length):

r_length = get_length(string

, index)

if max_length max_length =r_length

return

max_length

def get_length(

string

, index):

# 迴圈求出index為中心的最長回文字串

length = 0

r_ = len(string)

for i in range(1,index+1

):

if index+i < r_ and string[index-i] == string[index+i]:

length += 1

else

:

break

return

length

if __name__ == "

__main__":

result = max_substr("

35534321")

print (result)

功能已經實現了,經過測試也沒有 bug,但是我們靜下心來想一想,目前的解法是否還有優化空間呢?根據目前的解法,我們求出了『35534321『中每個元素中心的最大回文子串。當遍歷到'4'時,我們已經知道目前最長的回文子串的長度 max_length 是 4,這是我們求出了以 4 為中心的最長回文子串長度是 3,它比 max_length 要小,所以我們不更新 max_length。換句話說,我們計算以 4 為中心的最長回文字串長度是做了無用功。這就是我們要優化的地方,既然某個元素的最長的回文子串長度並沒有超過 max_length,我們就沒有必要計算它的最長回文子串,在遍歷乙個新的元素時,我們要優先判斷以它為中心的回文子串的長度是否能超越 max_length,如果不能超過,就繼續遍歷下乙個元素。以下是優化後的實現:

#

!/usr/bin/python

#-*- coding: utf-8 -*-

defmax_substr(string):

s_list = [s for s in

string]

string = '

#' + '

#'.join(s_list) + '#'

max_length =0

length =len(string)

for index in

range(0, length):

r_length =get_length2(string, index, max_length)

if max_length max_length =r_length

return

max_length

defget_length2(string, index, max_length): #

基於已知的最長字串求最長字串

#1.中心+最大半徑超出字串範圍, return

r_ =len(string)

if index + max_length >r_:

return

max_length #

2.無法超越最大半徑, return

l_string = string[index - max_length + 1 : index + 1]

r_string = string[index : index +max_length]

if l_string != r_string[::-1]:

return

max_length #

3.計算新的最大半徑

result =max_length

for i in

range(max_length, r_):

if index-i >= 0 and index+i < r_ and string[index-i] == string[index+i]:

result += 1

else

:

break

return result - 1

if__name__ == "

__main__":

result = max_substr("

35534321")

print (result)

leetcode上原題解答如下:

class

solution: #

從中心向外擴散

defhelper(self, s, l, r):

while l >= 0 and r < len(s) and s[l] ==s[r]:

l -= 1; r += 1

return s[l+1:r] #

o(n^2)時間複雜度方法

deflongestpalindrome(self, s):

res = ""

for i in

range(len(s)):

#單核回文如 "aba"

tmp =self.helper(s, i, i)

if len(tmp) >len(res):

res =tmp

#雙核回文如 "abba"

tmp = self.helper(s, i, i+1)

if len(tmp) >len(res):

res =tmp

return

res**:

在乙個字串中尋找另外乙個字串

在乙個字串中尋找另外乙個字串 public class text foundit true break test system.out.println foundit?found it didn t find it 該段程式有點難以理解,主要就是if語句的理解,if searchme.charat ...

php判斷乙個字串包含另乙個字串

a 58252,58253 如果 a 中存在 b,則為 true 否則為 false。b 58253 if strpos a,b false else 查詢字串在陣列中出現的次數 array array 1,hello 1,world hello 11 計算 string在 array 需為陣列 中...

SQL 判斷乙個字串是否在另外乙個字串中

eg str1 admin str2 1234,123admin,xcxx 比較str1是否在str2中 用常用的charindex,返回肯定是有值的,這裡自己動手寫乙個方法 檢查乙個字串是否在另外乙個字串中數,另外乙個字串元素用,隔開 create function dbo checkstrina...