647. 回文子串
题目:
第一次思考:
- 首先想到打直球
实现:
class Solution {
public:bool count(string s,int i,int j){bool ref=true;while(i<j){if (s[i++]!=s[j--]){ref=false;break;}}return ref;}int countSubstrings(string s) {int ref=0;for(int i=0;i<s.size();i++){for (int j=i;j<s.size();j++){if (count(s,i,j))ref++;}}return ref;}
};
解释:
- 对于每个子串去判断是不是回文
第二次思考:
- 第一次的还是太慢了,慢在对于每一个子串都需要进行一次传统的回文串判断
- 于是想到(涉及子串)动态规划
- 难在转移方程:对于每个需要判断的字符串,首先首尾相等,其次去除掉首尾后的子串也是回文串。
实现:
class Solution {
public:int countSubstrings(string s) {int ref=0;int size=s.size();vector<vector<bool>> dp(size,vector<bool>(size,false));for (int i=0;i<size;i++){dp[i][i]=true;}int length=1;while (length<size){int l=0;int r=l+length;while (r<size){if (s[l]==s[r]){if (length<2||dp[l+1][r-1]){dp[l][r]=true;}}l++;r++;}length++;}for (int i=0;i<size;i++){for (int j=i;j<size;j++){if (dp[i][j])ref++;}}return ref;}
};
第三次思考:
- 如果不使用动态规划,就可以省下dp的空间了
- 使用中心扩展法
- 使用中心扩展法需要考虑s的size的奇偶性,于是使用manacher改版
实现:
class Solution {
public:int countSubstrings(string s) {int ref=0;string manachered="";manachered.push_back('#');for (auto c:s){manachered.push_back(c);manachered.push_back('#');}ref=manachered.size();for (int i=0;i<manachered.size();i++){int l=i-1;int r=i+1;while(l>=0&&r<manachered.size()){if (manachered[l]==manachered[r]){ref++;}else{break;}l--;r++;}}return ref;}
};