leetcode647.回文子串

参考:https://www.cnblogs.com/AlvinZH/p/8527668.html

回文串特点:以中间的一个(奇数个)或者两个(偶数个)字母为中心是对称的
1.动态规划
dp[i][j]表示i—j之间的序列是否是回文串,如果是为True否则为False,那么递推公式为:
(1)如果s[i] != s[j]那么就不是回文串
(2)如果s[i] == s[j] 那么 dp[i][j] = dp[i+1][j-1]
公式含义为:如果i+1到j-1的序列是回文串,且s[i] == s[j]那么说明i到j也是回文串,如果i+1到j-1不是回文串,那么i到j也不是回文串
上述公式要成立需要满足:i+1,即j-i>2
那么考虑j-i<=2的情况:
1.j-i=0,即j=i,即一个字母本身他就是回文串
2.j-i=1,即i,j相邻,且两个字母相等s[i]=s[j],那么也是回文串
3.j-i=2,即j和i之间有一个字母,且s[i]=s[j],那么也是回文串,如ABA

代码:

class Solution {
     
public:
    int countSubstrings(string s) {
     
        int len = s.size(), res = 0;
        vector<vector<bool>> dp(len, vector<bool>(len, false));
        for (int i = len - 1; i >= 0; --i) {
     
            for (int j = i; j < len; ++j) {
     
                dp[i][j] = (s[i] == s[j]) && (j - i <= 2 || dp[i + 1][j - 1]); 
                if (dp[i][j]) ++res;
            }
        }
        return res;
    }
};

代码中

dp[i][j] = (s[i] == s[j]) && (j - i <= 2 || dp[i + 1][j - 1]);

可以写成

if(s[i] != s[j]) 
	dp[i][j] = False;
else if(s[i]==s[j] && j-i<=2) 
	dp[i][j] = True;
else 
	dp[i][j] = dp[i+1][j-1];

下面看一下循环变量:
j-i<=2的情况每个位置不需要依赖其他位置就可以决定自己的值
对于其他位置,由递推公式可以看出一个位置的值是由其左下角的值决定的
leetcode647.回文子串_第1张图片
2.回文中心
将每个字母分别作为回文中心然后向两边扩展,分两种情况,一种是自己为中心,第二种自己和下一个一起为中心

class Solution {
     
public:
    int countSubstrings(string s) {
     
        int len = s.size(), res = 0;
        for (int i = 0; i < len; ++i) {
     
            int mid1 = i, mid2 = i;//奇数
            while (mid1 >= 0 && mid2 < len && s[mid1] == s[mid2]) {
      //两边不能超过原字符串的边界
                --mid1; ++mid2; ++res;
            }
            
            mid1 = i, mid2 = i+1;//偶数
            while (mid1 >= 0 && mid2 < len && s[mid1] == s[mid2]) {
     
                --mid1; ++mid2; ++res;
            }
        }
        return res;
    }
};

3,马拉车算法没看

你可能感兴趣的:(leetcode)