You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
这道题给了一个字符串,让我们计算有多少个回文子字符串。博主看到这个题,下意识的想着应该是用 DP 来做,哼哼哧哧写了半天,修修补补,终于通过了,但是博主写的 DP 不是最简便的方法,略显复杂,这里就不贴了。还是直接讲解大神们的解法好了。其实这道题也可以用递归来做,而且思路非常的简单粗暴。就是以字符串中的每一个字符都当作回文串中间的位置,然后向两边扩散,每当成功匹配两个左右两个字符,结果 res 自增1,然后再比较下一对。注意回文字符串有奇数和偶数两种形式,如果是奇数长度,那么i位置就是中间那个字符的位置,所以左右两遍都从i开始遍历;如果是偶数长度的,那么i是最中间两个字符的左边那个,右边那个就是 i+1,这样就能 cover 所有的情况啦,而且都是不同的回文子字符串,参见代码如下:
解法一:
class Solution {
public:
int countSubstrings(string s) {
if (s.empty()) return 0;
int n = s.size(), res = 0;
for (int i = 0; i < n; ++i) {
helper(s, i, i, res);
helper(s, i, i + 1, res);
}
return res;
}
void helper(string s, int i, int j, int& res) {
while (i >= 0 && j < s.size() && s[i] == s[j]) {
--i; ++j; ++res;
}
}
};
class Solution {
public:
int countSubstrings(string s0) {
string s="$#";
s.reserve(2+s0.size()*2);
for(int i = 0; i < s0.size(); ++i){
s+= s0[i]; s+='#';
}
vector maxRadius(s.size(), 0);
int right =0, center = 0;
int total = 0;
for(int i = 1; i < s.size(); ++i){
int left = 2 * center - i;
maxRadius[i] = right > i? min(maxRadius[left], right -i) : 1;
while(s[i+maxRadius[i]]== s[i-maxRadius[i]]) ++maxRadius[i];
if(maxRadius[i] +i > right){
right = maxRadius[i]+1;
center = i;
}
total += maxRadius[i]/2;
}
return total;
}
};
Activity
lld2006 commentedon Jun 17, 2020
这个不是马拉车算法吗? 为什么搞得这么复杂?最大半径/2 加在一起就可以了
class Solution {
public:
int countSubstrings(string s0) {
string s="$#";
s.reserve(2+s0.size()*2);
for(int i = 0; i < s0.size(); ++i){
s+= s0[i]; s+='#';
}
vector maxRadius(s.size(), 0);
int right =0, center = 0;
int total = 0;
for(int i = 1; i < s.size(); ++i){
int left = 2 * center - i;
maxRadius[i] = right > i? min(maxRadius[left], right -i) : 1;
while(s[i+maxRadius[i]]== s[i-maxRadius[i]]) ++maxRadius[i];
if(maxRadius[i] +i > right){
right = maxRadius[i]+1;
center = i;
}
total += maxRadius[i]/2;
}
return total;
}
};