647. 回文子串
給定乙個字串,你的任務是計算這個字串中有多少個回文子串。
具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被計為是不同的子串。
示例 1:
輸入: 「abc」
輸出: 3
解釋: 三個回文子串: 「a」, 「b」, 「c」.
示例 2:
輸入: 「aaa」
輸出: 6
說明: 6個回文子串: 「a」, 「a」, 「a」, 「aa」, 「aa」, 「aaa」.
注意:輸入的字串長度不會超過1000。
回文的資料量不大,所以可以考慮使用o(n*n)的方法。
首先是動態歸的方法:由於當個的字元也是乙個回文串,所以我們設定dp table的時候,設定為二維的dp, dp[i][j]表示為索引i~j內是否構成回文串。
下面的配圖來自:
可以看到,一致的單個的字串是回文串,所以中間的b是回文, dp[2][2] =true, 之後我們考慮dp[i+1][j-1]的狀態,可以看出 s[i+1] == s[j-1],並且內部的是s[2]還是乙個回文,所以dp[i+1][j-1]也是回文。由此可以推出動態轉移方程:
d p[
i][j
]=dp
[i+1
][j−
1];i
f:s[
i]==
s[j]
dp[i][j] = dp[i+1][j-1] ; if :s[i] == s[j]
dp[i][
j]=d
p[i+
1][j
−1];
if:s
[i]=
=s[j
]還有一種特殊情況就是當 j == i + 1,並且 s[i] == s[j],這個時候可以直接賦值dp[i][j] = true。
class
solution
:def
countsubstrings
(self, s:
str)
->
int:
n =len(s)
out =
0 dp =[[
false
]*n for _ in
range
(n)]
for i in
range
(n):
#對角線上乙個元數全為true
dp[i]
[i]=
true
for i in
range
(n-1,-
1,-1
):for j in
range
(i+1
, n)
:if s[i]
== s[j]
:#如果兩個元數相等
if j-
1== i:
#並且兩個元數相鄰
dp[i]
[j]=
true
#直接賦值true
else
:#否則當前的dp狀態和之前內部的狀態有關
dp[i]
[j]= dp[i+1]
[j-1
]else
:#不等,直接賦值false
dp[i]
[j]=
false
if dp[i]
[j]==
true
:#統計右上角的回文個數
out +=
1# print(dp)
return out+n
除此之外還有一種中心展開的方法,分別以奇數回文和偶數回文進行展開。
class
solution
:def
countsubstrings
(self, s:
str)
->
int:
n =len(s)
self.out =
0def
count
(s, i, j)
:while
0<= i and j < n:
if s[i]
== s[j]
: self.out +=
1 i -=
1 j +=
1else
:break
for i in
range
(n):
count(s, i, i)
#統計奇回文
count(s, i, i+1)
#統計偶回文
return self.out
leetcode647 回文子串
給定乙個字串,你的任務是計算這個字串中有多少個回文子串。具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被計為是不同的子串。示例 輸入 aaaba 輸出 9 解釋 a aa a aa aaa a b aba a 奇回文 如 aba 和偶回文 如abba 歸一化處理 i 0123 47s...
leetcode 647 回文子串
給定乙個字串,你的任務是計算這個字串中有多少個回文子串。具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被計為是不同的子串。示例 1 輸入 abc 輸出 3 解釋 三個回文子串 a b c 示例 2 輸入 aaa 輸出 6 說明 6個回文子串 a a a aa aa aaa 注意 輸入...
LeetCode 647 回文子串
題目鏈結 題目描述 給定乙個字串,你的任務是計算這個字串中有多少個回文子串。具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被計為是不同的子串。示例輸入 abc 輸出 3 解釋 三個回文子串 a b c 輸入 aaa 輸出 6 說明 6個回文子串 a a a aa aa aaa 注意 ...