正如孔乙己知道「回」字有四種寫法
這個問題也有四種解決的方法
暴力法列舉這個字串的所有子串,再判斷是否為回文。時間複雜度為 o(n^3)
此處不實現,太弱智了
中心擴充套件法
從字串的每乙個字元開始,以此為中心,向兩側擴充套件,直到不是回文為止。
這種方法的時間複雜度是 o(n^2)。但是要考慮到許多特殊情況。如 bb,abbbb,bbbb 等偶數個的回文,所以邏輯上比較複雜。使用這種方法打敗了接近 50% 的 python 提交。
def
longestpalindrome
(self, s)
:"""
:type s: str
:rtype: str
"""r =
''for i in
range(0
,len
(s))
: temp = s[i]
j = i -
1 k = i +
1while j >=
0and k <
len(s)
and s[j]
== s[k]
: temp = s[j]
+ temp + s[k]
j -=
1 k +=
1# 識別如 abba 這種的回文
if k <
len(s)
and k == i +
1and s[k]
== s[i]
: temp += s[k]
j = i -
1 k +=
1while j >=
0and k <
len(s)
and s[j]
== s[k]
: temp = s[j]
+ temp + s[k]
j -=
1 k +=
1# 識別如 aabbbbaa 這種回文if1
< k <
len(s)
and s[k]
== s[i]
and temp.count(s[i])==
len(temp)
: temp += s[k]
k +=
1while j >=
0and k <
len(s)
and s[j]
== s[k]
: temp = s[j]
+ temp + s[k]
j -=
1 k +=1if
len(temp)
>
len(r)
: r = temp
return r
動態規劃法
假設 dp[i, j] = 1 表示 s[i…j] 為回文,則有 dp[i, j] = 1 —> dp[i+1, j-1] = 1
所以得到狀態轉移方程
d p[
i,j]
=dp[i+1, j-1], & \text \\ 0, &\text \end
dp[i,j
]={d
p[i+
1,j−
1],0
,s[i] = s[j]s[
i]!=s
[j]
dp 陣列的初始化
dp[i,i] = 1
dp[i,i+1] = 1 if s[i] == s[i+1]
def
longestpalindrome
(self, s)
:"""
:type s: str
:rtype: str
"""ifnot s or
len(s)==1
:return s
dp =[[
false
for j in
range
(len
(s))
]for i in
range
(len
(s))
] longest =
1 start =
0# 初始化 dp
for i in
range(0
,len
(s))
: dp[i]
[i]=
true
if i +
1<
len(s)
and s[i]
== s[i+1]
: dp[i]
[i+1]=
true
start = i
longest =
2for l in
range(3
,len
(s)+1)
:# 列舉子串長度
for i in
range(0
,len
(s)- l +1)
:# 列舉子串的起始點
j = l + i -
1if s[i]
== s[j]
and dp[i+1]
[j-1]:
dp[i]
[j]=
true
start = i
longest = l
return s[start: start + longest]
manacher 演算法
該演算法的介紹在
以下是其用 python 的實現( faster than 93.25% of python online submissions )
def
longestpalindrome
(self, s)
:"""
:type s: str
:rtype: str
"""ifnot s or
len(s)==1
:return s
t ='$#'
+'#'
.join(s)
+'#'
p =[0
]*len(t)
# p[i] 表示以 t[i] 為中心的回文的最大半徑
mx =0id
=0reslen =
0# 記錄全域性最大的半徑
rescenter =
0for i in
range(1
,len
(t))
: p[i]
=min
(p[2*id
- i]
, mx - i)
if mx > i else
1while i + p[i]
<
len(t)
and i - p[i]
>=
0and t[i + p[i]
]== t[i - p[i]]:
p[i]+=1
if mx < i + p[i]-1
: mx = i + p[i]-1
id= i
if reslen < p[i]
: reslen = p[i]
rescenter = i
return s[
(rescenter - reslen)//2
:(rescenter - reslen)//2
+ reslen -
1]
高效的求最長回文子串的演算法 Manacher
gdoi市選出了一道關於manacher的題目,於是打算學一下,但因為網路流鴿了一陣,最近才學完,學完後表示複雜度有點迷。manacher,俗稱馬拉車,是由一位名叫manacher的人與1975年提出的,這個演算法讓求最長回文子串的複雜度從o n 2 下降到了o n 先從n方演算法說起,n方演算法是...
最長回文子串 最長回文子串行
1.最長回文子串行 可以不連續 include include include include using namespace std 遞迴方法,求解最長回文子串行 intlps char str,int i,int j intmain include include include using n...
最長回文子串
描述 輸入乙個字串,求出其中最長的回文子串。子串的含義是 在原串連續出現的字串片段。回文的含義是 正著看和倒著看是相同的,如abba和abbebba。在判斷是要求忽略所有的標點和空格,且忽略大小寫,但輸出時按原樣輸出 首尾不要輸出多餘的字串 輸入字串長度大於等於1小於等於5000,且單獨佔一行 如果...