代码随想录算法训练营第五十七天| 647. 回文子串,516. 最长回文子序列,5. 最长回文子串
647. 回文子串
题目链接:回文子串
动态规划
s = ‘cbabc’,如果判断这是否是回文串,那么最好的方式是
- 判断中间的字符串
s[1:(len(s)-1]
是否为回文串 - 判断
s[0]
和s[len(s)-1]
是不是相等 - 都是那么s就是回文串
所以这个遍历的顺序应该是如果s[i]
和s[j]
相等的,那么dp[i][j]
就应该等于左下方(中间部分)的判断也就是dp[i+1][j-1]
class Solution:
def countSubstrings(self, s: str) -> int:
# dp[i][j] = 以s[i:j]是否为回文子串。
dp = [[False]*len(s) for _ in range(len(s))]
dp[0][0] = True
res = 1
for i in range(1,len(s)):
dp[i][i] = True
res += 1
if s[i-1] == s[i]:
res += 1
dp[i-1][i] = True
for j in range(2,len(s)):
for i in range((j-1)):
if s[j] == s[i]:
dp[i][j] = dp[i+1][j-1]
if dp[i][j] == True:
res += 1
return res
双指针
s = ‘cbabc’
- 以中心点a为起点
- 判断a, bab, cbabc
- 以ba为起点
- 判断ba, cbab
- 以ab为起点
- 判断ab, babc
- 以此类推
这里只有一个while主要是因为他是从中心点往外扩散的,如果中心点就不是回文串了,那外面肯定不是,也不用出去了。
class Solution:
def countSubstrings(self, s: str) -> int:
def test(s,i,j):
res = 0
while i>=0 and j<len(s) and (s[i] == s[j]):
i -= 1
j += 1
res += 1
return res
res = 0
for i in range(len(s)):
res += test(s,i,i)
res += test(s,i,i+1)
return res
516. 最长回文子序列
题目链接:最长回文子序列
s = ‘bbbab’
和上一题一样,
- 如果
s[i]
和s[j]
相等的,那么dp[i][j]
就应该等于左下方(中间部分)的判断也就是dp[i+1][j-1]+2
- 如果不相等的那就看
i-1
到j
或者i
到j-1
的最大值是多少。 - 顺便我自己的代码去管
dp[i-1][i]
纯粹是多此一举,因为递推公式能管到。
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
# dp[i][j] = i到j内的最长的回文子序列长度.
dp = [[0]*len(s) for _ in range(len(s))]
dp[0][0] = 1
for i in range(1,len(s)):
dp[i][i] = 1
if s[i-1] == s[i]:
dp[i-1][i] = 2
else:
dp[i-1][i] = 1
for j in range(2,len(s)):
for i in range((j-1),-1,-1):
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i][j-1],dp[i+1][j])
return dp[0][-1]
5. 最长回文子串
题目链接:最长回文子串
用了第一题的代码,把回文子串的长度都记下来,找出最大的那个。
class Solution:
def longestPalindrome(self, s: str) -> str:
dp = [[False]*len(s) for _ in range(len(s))]
dp[0][0] = True
diff = 0
res = s[0]
for i in range(1,len(s)):
dp[i][i] = True
if s[i-1] == s[i]:
diff = 2
res = s[(i-1):(i+1)]
dp[i-1][i] = True
for j in range(2,len(s)):
for i in range((j-1)):
if s[j] == s[i]:
dp[i][j] = dp[i+1][j-1]
if dp[i][j] == True and (j-i+1>diff):
diff = j-i+1
res = s[i:(j+1)]
return res