647. 回文子串(C++)

题目描述:

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

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

示例 1:

输入: "abc"

输出: 3

解释: 三个回文子串: "a", "b", "c".

示例 2:

输入: "aaa"

输出: 6

说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".

注意:

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

思想1:动态规划

状态:dp[i][j] 表示字符串s在[i,j]区间的子串是否是一个回文串。

状态转移方程:当 s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1]) 时,dp[i][j]=true,否则为false

状态转移方程的含义:

  • 当只有一个字符时,比如a自然是一个回文串。
  • 当有两个字符时,如果是相等的,比如aa,也是一个回文串。
  • 当有三个及以上字符时,比如ababa这个字符记作串1,把两边的a去掉,也就是bab记作串2,可以看出只要串2是一个回文串,那么左右各多了一个a的串1必定也是回文串。所以当s[i]==s[j]时,自然要看dp[i+1][j-1]是不是一个回文串。

代码1:

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

思想2:中心扩展法

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

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

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

如果上面看不太懂的话,还可以看看下面几个问题:

为什么有 2 * len - 1 个中心点?

  • aba 有5个中心点,分别是 a、b、c、ab、ba
  • abba 有7个中心点,分别是 a、b、b、a、ab、bb、ba

什么是中心点?

  • 中心点即left指针和right指针初始化指向的地方,可能是一个也可能是两个

为什么不可能是三个或者更多?

  • 因为3个可以由1个扩展一次得到,4个可以由两个扩展一次得到

代码2:

class Solution {
public:
    int countSubstrings(string s) {
        int count = 0;
        int len = s.size();
        for(int center=0;center<2 * len -1;center++){
            //left和right指针和中心点的关系是:left有一个很明显的2倍关系的存在,其次是right,       //可能和left指向同一个(偶数时),也可能往后移动一个(奇数)
            int left = center / 2;
            int right = left + center % 2;
            while(left>=0 && right<len && s[left]==s[right]){
                count++;
                left--;
                right++;
            }
        }
        return count;
    }
};

原文链接: https://www.cnblogs.com/thefatcat/p/12883277.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/197302

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午7:31
下一篇 2023年2月12日 下午7:31

相关推荐