来源:力扣(LeetCode)
链接: https://leetcode.cn/problems/palindromic-substrings/
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:
输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
提示:
- 1 <= s.length <= 1000
- s 由小写英文字母组成
有其他的解法,比如中心扩散,马拉车等,可以参考官方题解。
- 动态规划:前后字符有关联,可以使用暴力搜索或者动态规划,由于暴力搜索复杂度太高,这里只考虑动态规划
动态规划:四个步骤:- 问题定义
- 状态转移方程
- 初始条件和边界情况
- 确定计算顺序(自顶向下,还是自下向上)
问题定义:
字符串是一个连续的字符组合,因此不能只单独的考虑其中一个,另外起点也不都是从0下标开始,可以从前面任何一个位置开始,因此不能直接定义dp[i]来表示前i个字符有多少个回文字符串,而是用二维dp[i][j]表示
定义dp[i][j] 表示字符下标 i 到下标 j 组成的字符串是否为回文串,其中 0≤i≤j,0≤j≤n。
状态转移方程:
如果dp[i][j]是True,则有dp[i+1][j-1]也是回文子串,且s[i]==s[j]
这里需要考虑i,j的距离。如果二者是相邻的,且s[i]==s[j]同样满足条件。
初始化条件和边界条件
- dp = [[False] * n for _ in range(n)]
确定计算顺序:
这个是从下向上的方向计算即可
python实现
class Solution:
def countSubstrings(self, s: str) -> int:
n = len(s)
if n == 1:
return 1
# dp[i][j] 表示s[i:j]是否是一个回文串
dp = [[0] * n for _ in range(n)]
count = 0
for j in range(n):
for i in range(j, -1, -1):
if s[i] == s[j] and (j-i < 2 or dp[i+1][j-1]):
dp[i][j] = True
count += 1
return count
c++实现
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
if (n == 1) return 1;
vector<vector<bool>> dp(n, vector<bool>(n, false));
int count = 0;
for (int j=0; j<n; j++) {
for(int i=j; i>=0; i--) {
if (s[i] == s[j] && (j-i<2 || dp[i+1][j-1])) {
dp[i][j] = true;
count++;
}
}
}
return count;
}
};
复杂度分析
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n 2 ) O(n^2) O(n2)
- https://leetcode.cn/problems/palindromic-substrings/solution/by-lfool-2mvg/
- https://leetcode.cn/problems/palindromic-substrings/solution/hui-wen-zi-chuan-by-leetcode-solution/
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)