45/300
- 回文子串
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
示例 1:
输入: “abc”
输出: 3
解释: 三个回文子串: “a”, “b”, “c”.
示例 2:
输入: “aaa”
输出: 6
说明: 6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”.
注意:
输入的字符串长度不会超过1000。
动态规划类型,第三道:
举例X属于未知数字。 ‘aXXb’肯定不是回文,如果是 ‘aXXa’ 呢?
需要判断中间两位是不是回文,如果这个状态True/False已经被记录,可以直接调取。
同理,'aXb’肯定不是回文,‘aXa’ 则需调取X的状态。
再小一点‘ab’,‘aa’我们可以直接判断True or False。
最小到‘a’,‘b’直接记录True
我们把思路从底往上实现:
‘abca’
0 1 2 3
[ a, b, c, a],
0 [a, T, F, F, F],
1 [b, , T, F, F],
2 [c, , , T, F],
3 [a, , , , T]
class Solution:
def countSubstrings(self, s):
"""
:type s: str
:rtype: int
"""
if not s: return 0
n = len(s)
#n*n的小本本准备好
memo = [[None]*n for _ in range(n)]
count = 0 #遇True则+1
#记录'a','b' = True
for i in range(n):
memo[i][i] = True
count += 1
for j in range(1,n):
for i in range(j):
# 'abcd'
# j = 1, i = 0 [0][1]ab
# j = 2, i = 0, 1 [0][2]ac [1][2]bc
# j = 3, i = 0, 1, 2 [0][3]abcd [1][3]bcd [2][3]cd
#'aa' 'aXa'
if s[i] == s[j] and j-i <= 2:
memo[i][j] = True
count += 1
#'aXXa' 'aXXXa'
elif s[i] == s[j] and j-i > 2:
#调取状态
if memo[i+1][j-1]:
memo[i][j] = True
count += 1
else:
memo[i][j] = False
#'ab''aXb''aXXb'..
else:
memo[i][j] = False
return count
但,从大佬处发现了更高效的办法!
画个思路丑图:‘abcded’
class Solution:
def countSubstrings(self, s):
"""
:type s: str
:rtype: int
"""
if not s: return 0
n = len(s)
count = 0
for i in range(2*n-1):
l = i//2;r = (i+1)//2
while l >= 0 and r < n and s[l] == s[r]:
count += 1
l -= 1; r += 1
return count