题目要求:
给定一个字符串 s
,请计算这个字符串中有多少个回文子字符串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:
输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
提示:
1 <= s.length <= 1000
s
由小写英文字母组成
解法-1 动态规划 O(N^2):
这道题可以使用dp表保存所有子串状态:
创建一个二维dp表,dp[i][j]保存以s[j]为开头、s[i]为结尾的子串是否为回文,状态转移方程如下:
如果s[j] != s[i],则必不会是回文,dp[i][j] = false;
如果s[j] == s[i]:
(1)并且i==j,只有一个字母一定是回文;
(2)并且j == i-1,两个相同字母也一定是回文;
(3)并且j < i-1 && dp[i-1][j+1],它们中间有字符,且中间的子串也是回文,则一定是回文。
cpp
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
vector<vector<bool>> dp(n);
for (int i = 0; i < n; i++)
dp[i].resize(i + 1, true);
int ret = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j <= i; j++) {
if (s[i] != s[j])
dp[i][j] = false;
else if (j < i - 1) // i、j中间有其他字符
dp[i][j] = dp[i - 1][j + 1];
ret += dp[i][j] ? 1 : 0;
}
}
return ret;
}
};