20200406——第六百四十七题 回文子串

动态规划

如果给定一个区间,i,j 字符串如果a[i] == a[j] ,那么就判断a[i+i] 与a[j-1]是否相等一直到偶数或者奇数形式,判断这个字符串是不是回文字符串。

状态:dp[i][j] 表示字符串s在[i,j]区间的子串是否是一个回文串。
状态转移方程:当 s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1]) 时,dp[i][j]=true,否则为false

class Solution {
    public int countSubstrings(String s) {
        //有一个二维的boolean类型的数组来进行判断
        boolean[][] flag = new boolean[s.length()][s.length()];
        int ans =0;

        for(int i = 0;i<s.length();++i){
            for(int j = 0;j<=i;++j){
                if(s.charAt(j) == s.charAt(i) && ((i-j<2) || flag[j+1][i-1] == true)){
                    flag[j][i] = true;
                    ans++;
                }
            }
        }
        return ans;
    }
}

在这里插入图片描述
要注意,i是大的数在右边,所以判断的时候是i-j,j是小的数,在左边。

中心扩展法
这是一个比较巧妙的方法,实质的思路和动态规划的思路类似。

比如对一个字符串ababa,选择最中间的a作为中心点,往两边扩散,第一次扩散发现left指向的是b,right指向的也是b,所以是回文串,继续扩散,同理ababa也是回文串。

这个是确定了一个中心点后的寻找的路径,然后我们只要寻找到所有的中心点,问题就解决了。

中心点一共有多少个呢?看起来像是和字符串长度相等,但你会发现,如果是这样,上面的例子永远也搜不到abab,想象一下单个字符的哪个中心点扩展可以得到这个子串?似乎不可能。所以中心点不能只有单个字符构成,还要包括两个字符,比如上面这个子串abab,就可以有中心点ba扩展一次得到,所以最终的中心点由2 * len - 1个,分别是len个单字符和len - 1个双字符。

a b a 中心点就有 aba 三个字符 以及 ab 和 ba之间的空隙
偶数同此

举个例子
假如是abcedf
center的取值范围为0 ~12-1
right与left的指向就是中心点
可能指向同一个点,那么该点第一次判断一定是true,加入都指向b,ans++,下一步left指向a right指向b,这样不等于之后就跳出循环。

同理可知,right与left不指向同一个节点,可能指向前后两个节点ce,这种

class Solution {
    public int countSubstrings(String s) {
        int  ans = 0;
        for(int center = 0;center<s.length()*2 -1 ;++center){
            int left = center/2;
            int right = left+center%2;
            while(left>=0 && right<s.length()&& s.charAt(left) == s.charAt(right)){
                left--;
                right++;
                ans++;
            }
        }
        return ans;
    }
}

在这里插入图片描述

发布了955 篇原创文章 · 获赞 43 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36344771/article/details/105341470