给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

    回文字符串 是正着读和倒过来读一样的字符串。

    子字符串 是字符串中的由连续字符组成的一个序列。

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

    分析:本题有两种方法,相对来说,中心扩散法容易想,也更快更便捷,动态规划法也还行,两种方法都要掌握
    方法一:动态规划:
    用动态规划做我们就要想明白dp数组怎么建,含义是啥。
    回文子串,那么要有首尾进行判断,必须建立二维dp数组,dp[i][j]在本题中可以表示为boolean型变量,意思是以i为首,j为尾的字符串是否为dp数组。
    如何得到?首先要判断i和j的字符是否相等,不相等那么一定不是
    相等后,要思考,有三种情况:
    i和j表示的是一个数,那么不需要别的判断,为true;
    i和j表示的是相邻的两个数,那么也可以,为true;
    i和j中间还有其他数,这时候就需要dp数组进行推导了,即需要判断dp[i+1][j-1]是否为true,是的话dp[i][j]也为true;
    初始化,所有的都要初始化为false;
    遍历顺序?本题在遍历顺序上也有讲究,从递推公式中可以看出,dp[i][j]的推导需要dp[i+1][j-1]的值,那么dp[i+1][j-1]就需要在dp[i][j]之前进行判断。i表示行数,j表示列数,我们需要自下向上自左至右,同时由于我们设定i为头,j为尾,那么在二维dp数组中我们需要填入的是右上的三角块的值。

    参考代码:
    public int countSubstrings(String s) {
    int ret=0;
    boolean[][] dp = new boolean[s.length()][s.length()];
    for(int i=s.length()-1;i>=0;i—){
    for(int j=i;j if(s.charAt(i)==s.charAt(j)){
    if(j-i<=1){
    ret++;dp[i][j]=true;
    }else if(dp[i+1][j-1]==true){
    dp[i][j]=true;ret++;
    }
    }
    }
    }
    return ret;
    }

    方法二:中心扩散法
    这个方法更容易理解,效率也更高,此题推荐这种解法;
    所谓中心扩散法,即以将一个字符或两个字符为中心,不断外扩,需要首尾两个指针,比较两个指针判断值是否相等,相等的话,结果+1,并继续外扩;
    需要一个或两个字符为中心,因为aba这种三个字符被包含在了一个字符的情况,而一个字符的情况不包含aa这种情况,所以需要一个或两个字符为中心,这样代码的设置也会十分巧妙。

    参考代码:
    public int countSubstrings(String s) {
    int ret=0;
    int left=0,right=0;
    for(int i=0;i left=i/2;
    right=left+i%2;
    while(left>=0&&right ret++;
    left—;
    right++;
    }
    }
    return ret;
    }