赞
踩
class Solution {
public:
int countSubstrings(string s) {
}
};
计算有多少个回文子串的最朴素的方法是枚举出所有的回文子串,而枚举出所有的回文子串又有两种思路,分别是:
复杂度分析:
在实现的时候,我们需要处理一个问题,就是如何有序的枚举所有可能的回文中心,我们需要考虑回文长度是奇数和偶数的两种情况
算法:
class Solution { int count = 0; //以left和right为中心点,求回文字符串的数量 void extend(std::string s, int left, int right){ int len = s.length(); while (left >= 0 && right < len && s[left--] == s[right++]){ ++count; } }; public: int countSubstrings(string s) { int len = s.length(); for (int i = 0; i < len; ++i) { extend(s, i, i); //回文的长度是奇数 extend(s, i, i + 1); } return count; } };
class Solution { public: int countSubstrings(string s) { int count = 0; //以left和right为中心点,求回文字符串的数量 auto extend = [&](std::string s, int left, int right){ int len = s.length(); while (left >= 0 && right < len && s[left--] == s[right++]){ ++count; } }; int len = s.length(); for (int i = 0; i < len; ++i) { extend(s, i, i); //回文的长度是奇数 extend(s, i, i + 1); } return count; } };
这题让求一个字符串中有多少个回文子串,子串必须是连续的,子序列可以不连续,这题可以使用动态规划来解决。
dp[i][j]
表示字符串s
在[i, j]
区间的子串是否是一个回文串。如果是dp[i][j]为true,否则为false。在确定递推公式时,就要分析如下几种情况。
整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。
当s[i]与s[j]不相等,那没啥好说的了, dp[i][j]
一定是false。
当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况
情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串
情况二:下标i 与 j相差为1,例如aa,也是回文子串
情况三:下标:i 与 j相差大于1的时候,
s[i]
与s[j]
已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1
区间,这个区间是不是回文就看dp[i + 1][j - 1]
是否为true。s[i]==s[j]
时,自然要看 dp[i+1][j-1]
是不是一个回文串。以上三种情况分析完了,那么递归公式如下:
if (s[i] == s[j]) {
if (j - i <= 1) { // 情况一 和 情况二
result++; // result就是统计回文子串的数量。
dp[i][j] = true;
} else if (dp[i + 1][j - 1]) { // 情况三
result++;
dp[i][j] = true;
}
}
s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1])
时,dp[i][j]=true,否则为falsedp[i][j]
可以初始化为true么? 当然不行,怎能刚开始就全都匹配上了。
所以dp[i][j]
初始化为false。
遍历顺序可有有点讲究了。
首先从递推公式中可以看出,情况三是根据dp[i + 1][j - 1]是否为true,在对dp[i][j]进行赋值true的。
dp[i + 1][j - 1]
在 dp[i][j]
的左下角,如图:
如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的。
所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的
class Solution { public: int countSubstrings(string s) { int len = s.size(); std::vector<std::vector<int>> dp(len, std::vector<int>(len, false)); int ans = 0; for (int i = len - 1; i >= 0; --i) { for (int j = i; j < len; ++j) { if(s[i] == s[j]){ if(j - i <= 1 || dp[i + 1][j - 1]){ ++ans; dp[i][j] = true; } } } } return ans; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。