LeetCode 647. 回文子串

题目链接

647. 回文子串

题目分析

这个题和那个最长回文子串一个道理,可以用中心扩展方法或者DP方法进行处理,这个题我优先使用了DP进行处理。

DP方法

由题目可知,我们每个字符都能成为一个单独的回文串,所以count初始值就应该为字符串的长度。
然后我们定义一个boolean的二维数组,其定义如下:

  • dp[i][j]代表字符串从i到j能否构成一个回文串

然后剩下的办法就很容易了,其状态转移方程如下:

  • 如果s[i] == s[j] 且 i == j -1 或者 dp[i+1][j-1] 的情况下,count自增,然后把当前dp[i][j]设置为true

i == j-1是因为如果这两个是相邻的情况下,直接就能构成新的回文串,直接判对即可。
dp[i+1][j-1]是因为如果当前位置要成为新回文串的话,那么其字串也应该为回文串。

这些都做完了,也代表base cases也出来了,我们利用二维数组的左下角,对角线元素应该都为true。

中心扩展方法

思想就是跟最长回文串一样,我们拿每一个元素作为起始点,然后以该点为起始点向左右两边扩展,扩展的条件为

  • left >= 0 && right < s.length()
  • s[left] == s[right]

满足以上条件,我们就把计数器加一,然后left--, right++。
当然这个方法需要分为回文串为奇数和回文串为偶数长度的情况。
这个方法应该是最容易实现的了。

代码实现

动态规划代码

class Solution {
    public int countSubstrings(String s) {
        int count = s.length();
        char[] str = s.toCharArray();
        boolean[][] dp = new boolean[s.length()][s.length()];
        for(int i = 1; i < s.length(); i++){
            dp[i][i] = true;
        }
        for(int j = 0; j < s.length(); j++){
            for(int i = j-1; i >= 0; i--){
                if(str[i] == str[j] && (i == j -1 || dp[i+1][j-1])){
                    dp[i][j] = true;
                    count++;
                }
            }
        }
        return count;
    }
}

中心扩展代码

class Solution {
    int num = 0;
    public int countSubstrings(String s) {
        for (int i=0; i < s.length(); i++){
            count(s, i, i);//回文串长度为奇数
            count(s, i, i+1);//回文串长度为偶数
        }
        return num;
    }
    
    public void count(String s, int start, int end){
        while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
            num++;
            start--;
            end++;
        }
    }
}
posted @ 2020-08-19 09:20  ZJPang  阅读(91)  评论(0编辑  收藏  举报