
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.回文子串
题目链接:647. 回文子串
题目分析:

子串和子数组是一样的。
具有不同开始位置或者结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
算法原理:
对于这道题相比于动态规划,中心扩展算法和马拉车算法更优秀。
中心扩展算法:时间复杂度O(N^2),空间复杂度O(1)
马拉车算法:时间复杂度O(N),空间复杂度O(N)
动态规划:时间复杂度O(N^2), 空间复杂度O(N^2)
动态规划虽然这里不是最优解,但是它的思想可以让有些回文串的困难题变成容易题。
能够将所有的子串是否是回文的信息,保存在 dp 表里面
1.状态表示
既然要把所有子串都放在dp表里面,一个一维dp肯定不够,

dp[i][j] 表示 s 字符串 [i, j] 的子串,是否是回文串
2.状态转移方程
判断 i - > j 是否是回文串,必须首先 i 位置 和 j 位置字符是相等的,如果都不相等,即使里面在好, i - > j 子串也不回文串

i 位置 和 j 位置字符相等,这里分三种情况:
i == j , ij同一个位置 是回文子串
i + 1 == j ,ij相邻 是回文子串
还有就是 i -> j 中间有别的字符,那就看 i + 1 位置 到 j - 1 位置的子串是否是回文子串,而i + 1 位 到 j - 1 是否是回文子串就在dp[i + 1][j - 1]

3.初始化
会发生越界的就只有 dp[i + 1][j -1],但是它会发生越界情况都已经在 i == j,i + 1 < j 这两种情况考虑到了。

4.填表顺序
dp[i][j] 可能会用到 dp[i + 1][j -1],所以从下往上填。

5.返回值
统计dp表中true的个数。
class Solution {
public:
int countSubstrings(string s) {
// 1.创建 dp 表
// 2.初始化
// 3.填表
// 4.返回值
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n));
int ret = 0;
for(int i = n - 1; i >= 0; --i)
{
for(int j = i; j < n; ++j)
{
if(s[i] == s[j])
{
dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
}
if(dp[i][j]) ret += 1; // 统计个数
}
}
return ret;
}
};
2.最长回文子串
题目链接: 5. 最长回文子串
题目描述:

算法原理:
如果上面那道题搞懂了,这道题完全直接就去做就行了。可以这样做:
判断子串是否是回文 —> 用 dp 表,统计所有子串是否是回文的信息 —> 根据 dp 表的起始位置得到我们想要的结果。
起始位置 i,回文串结束位置 j,回文串长度 j - 1 + 1
1.状态表示
dp[i][j] 表示 s 字符串 [i, j] 的子串,是否是回文串
2.状态转移方程

3.初始化
无需初始化,当用到 dp[i+1][j-1] 是有条件的,当 i + 1 < j才会用,此时不会越界。只有当 i == j,i + 1 == j 才会越界,但是我们已经特殊处理过了。
4.填表顺序
dp[i][j] 可能会用到 dp[i + 1][j -1],所以从下往上填。

5.返回值
dp 里面值为 true 的情况下,长度最大的子串的起始位置以及长度
class Solution {
public:
string longestPalindrome(string s) {
//1.创建 dp 表
//2.初始化
//3.填表
//4.返回值
int n = s.size(

最低0.47元/天 解锁文章
809





