mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
69 lines
1.9 KiB
Markdown
69 lines
1.9 KiB
Markdown
![]() |
# [647. Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/)
|
|||
|
|
|||
|
# 思路
|
|||
|
计算有多少个回文子串。
|
|||
|
|
|||
|
## 思路一、扩散法
|
|||
|
|
|||
|
根据回文串的定义,回文串是对称的。所以我们可以以字符串中的每个字符作为回文串中心位置,然后向两边扩散,每当成功匹配两个左右两个字符,就说明找到了一个回文串,res自增1。注意回文字符串有奇数和偶数两种形式,处理方式略有不同。
|
|||
|
|
|||
|
空间复杂度O(1), 时间复杂度O(n^2)
|
|||
|
|
|||
|
## 思路二、动态规划
|
|||
|
|
|||
|
还可以用动归来做:
|
|||
|
```
|
|||
|
dp[i][j] (i <= j) 定义成子字符串s[i,...,j]是否是回文串
|
|||
|
```
|
|||
|
所以初始状态就是`dp[i][i] = true`,状态转移方程为:
|
|||
|
```
|
|||
|
if s[i] == s[j] && (i+1 == j || dp[i+1][j-1]) :
|
|||
|
dp[i][j] = true
|
|||
|
```
|
|||
|
|
|||
|
空间复杂度O(n^2), 时间复杂度O(n^2),亲测比思路一慢不少
|
|||
|
|
|||
|
# C++
|
|||
|
## 思路一
|
|||
|
``` C++
|
|||
|
class Solution {
|
|||
|
public:
|
|||
|
int countSubstrings(string s) {
|
|||
|
int n = s.size(), res = 0;
|
|||
|
|
|||
|
for(int i = 0; i < n; i++){
|
|||
|
// 奇
|
|||
|
for(int j = 0; j <= min(i, n - 1 - i); j++){
|
|||
|
if(s[i-j] == s[i+j]) res++;
|
|||
|
else break;
|
|||
|
}
|
|||
|
// 偶
|
|||
|
for(int j = 1; j <= min(i+1, n - 1 - i); j++){
|
|||
|
if(s[i-j+1] == s[i+j]) res++;
|
|||
|
else break;
|
|||
|
}
|
|||
|
}
|
|||
|
return res;
|
|||
|
}
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
## 思路二
|
|||
|
``` C++
|
|||
|
class Solution {
|
|||
|
public:
|
|||
|
int countSubstrings(string s) {
|
|||
|
int n = s.size(), res = 0;
|
|||
|
|
|||
|
vector<vector<bool>>dp(n, vector<bool>(n, false));
|
|||
|
for(int i = n - 1; i >= 0; i--)
|
|||
|
for(int j = n - 1; j >= i; j--){
|
|||
|
if(s[i] == s[j] && (i == j || i+1 == j || dp[i+1][j-1])){
|
|||
|
dp[i][j] = true;
|
|||
|
res++;
|
|||
|
}
|
|||
|
}
|
|||
|
return res;
|
|||
|
}
|
|||
|
};
|
|||
|
```
|