描述

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

示例 1:

输入: "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c".
示例 2:

输入: "aaa"
输出: 6
说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
注意:

输入的字符串长度不会超过1000。

解析

[LeetCode] 5. 最长回文子串 ☆☆☆(最长子串、动态规划)类似,可以先考虑用中心扩展法,与其不同的是,记录回文子串个数。

也可以用动态规划。

思路为:

如果从i到j的字符串是回文字符串,那么如果i-1和j+1相等,那么从i-1到j+1就是回文字符串。
当然,如果是1个字符串,那么一定是回文的,如果是两个字符串,并且相等,那么也是回文的。

代码

中心扩展算法

public int countSubstrings(String s) {
        int count = 0;
        for (int i = 0; i < s.length(); i++) {
            count += count(s, i, i);//回文子串长度为奇数的情况
            count += count(s, i, i + 1);//回文子串长度为偶数的情况
        }
        return count;
    }
    
     public static int count(String s, int start, int end) {
        int count = 0;
        //start往左边跑,end往右边跑,注意边界
        while (start >= 0 && end < s.length() && s.charAt(start--) == s.charAt(end++)) {
            count++;
        }
        return count;
    }

动态规划

public static int countSubstrings(String s) {
        int result = 0;
        boolean[][] dp = new boolean[s.length()][s.length()];//i到j位置的字符串是否为回文子串

        for (int i = 0; i < s.length(); i++) {
            for (int j = 0; j <= i; j++) {
                if (i == j) {
                    dp[i][j] = true;//i j相等,肯定是回文子串
                } else {//i j不等的话,如果char一样,i j相差1,也符合;或者最近的内圈是回文子串
                    dp[i][j] = s.charAt(i) == s.charAt(j) && (j == i - 1 || dp[i - 1][j + 1]);
                }
                if (dp[i][j]) {
                    result++;
                }
            }
        }

//        for (int i = s.length() - 1; i >= 0 ; i--) {//类似,只是从后往前
//            for (int j = i; j < s.length(); j++) {
//                if (i == j)
//                    dp[i][j] = true;
//                else
//                    dp[i][j] = s.charAt(i) == s.charAt(j) && (j == i + 1 || dp[i + 1][j - 1]);
//                if (dp[i][j]) result++;
//            }
//        }
        return result;
    }

 

posted on 2019-12-19 12:25  反光的小鱼儿  阅读(414)  评论(0编辑  收藏  举报