首页 > 其他分享 >力扣 647. 回文子串

力扣 647. 回文子串

时间:2023-05-23 20:13:10浏览次数:53  
标签:子串 cnt 判断 力扣 647 字符串 dp 回文

647. 回文子串

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

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

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

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

示例 1:

输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"

示例 2:

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

题解

来自这里

题目要求统计给定字符串中回文子串的数量。可以使用动态规划来解决该问题。

首先,我们定义一个布尔类型的二维数组dp,其中dp[i][j]表示字符串s从索引i到索引j的子串是否是回文串。

然后,我们使用一个变量cnt来记录回文子串的数量,初始化为0。

接下来,我们遍历字符串s中所有可能的子串,从长度为1的子串开始逐渐增加长度。具体的遍历方式是通过两个循环控制,外层循环diff表示子串的长度,内层循环ij分别表示子串的起始索引和结束索引。

在遍历过程中,我们根据不同的子串长度分情况进行判断:

  1. 当子串长度为1时(即diff == 0),子串只有一个字母,必定是回文串,因此将dp[i][j]设置为true
  2. 当子串长度为2时(即diff == 1),子串有两个字母,如果这两个字母相等,则子串是回文串,否则不是回文串,根据判断结果将dp[i][j]设置为相应的布尔值。
  3. 当子串长度大于2时,需要判断子串的两个边缘字母和去掉边缘字母后的子串是否是回文串:
    • 如果去掉边缘字母后的子串是回文串(即dp[i+1][j-1]true),并且子串的边缘字母相等,则子串是回文串,将dp[i][j]设置为true;否则,子串不是回文串,将dp[i][j]设置为false

在更新dp[i][j]的同时,根据dp[i][j]的值判断子串是否是回文串,如果是,则将cnt加1。

最后,遍历完所有子串后,返回cnt作为结果,即回文子串的数量。

为什么只关注右上部分

在给定的代码中,只判断对角线右上部分的原因是为了避免重复计算和不必要的判断。

考虑一个回文子串,如果我们已经判断了它是回文串,那么它的左下部分(即索引差值大于0的部分)一定不会影响到它是否是回文串。因此,在计算过程中,我们只需要关注右上部分的子串即可。

举个例子来说明:

假设字符串s的长度为5,索引从0到4,那么我们需要判断的子串如下所示:

    0 1 2 3 4
0   * * * * *
1     * * * *
2       * * *
3         * *
4           *

对于位置(i, j),只有右上部分(包括对角线)的子串需要判断是否为回文串,而左下部分的子串已经在之前的迭代中进行过判断。例如,在计算位置(0, 2)时,我们已经计算过(1, 1)(2, 2)(3, 3)(4, 4)这几个位置的子串是否为回文串,因此不需要再重复计算。

通过只判断对角线右上部分的子串,我们可以有效地避免重复计算,减少了时间复杂度。

查看代码
 class Solution {
public:
    int countSubstrings(string s) {
        bool dp[s.length()][s.length()];
        int cnt=0;
        for(int diff=0;diff<s.length();++diff){//子串长度,也是横纵坐标i,j的差值
            for(int i=0,j=diff;j<s.length();++j,++i){//只判断右上部分的,左下部分全为false
                if(diff==0)
                    dp[i][j]=true;//对角线只有一个字母,肯定是true,(00,11,22...)
                else if(diff==1){
                    dp[i][j]=s[i]==s[j]?true:false;//对角线加右边的一个字母,共两个字母,判断,(01,12,23...)
                }else{
                    //结合判断a<bcc>b中的左右边缘字母和里面的<bcc>
                    if(dp[i+1][j-1])//里面的子串是回文,再判断里面的子串
                        dp[i][j]=s[i]==s[j]?true:false;
                    else//里面不是当前串肯定不是
                        dp[i][j]=false;
                }
                // if(dp[i][j])
                //     ++cnt;
                cnt=dp[i][j]?cnt+1:cnt;
            }
        }
        return cnt;
    }
};

标签:子串,cnt,判断,力扣,647,字符串,dp,回文
From: https://www.cnblogs.com/fudanxi/p/17426242.html

相关文章

  • 回文串和回文自动机
    1PAM简介1.1PAM的形式PAM是一个自动机,它的普通边组成了两棵树,fail边组成了一棵树。这两棵普通树分别表示主串中所有奇数长度的回文串和偶数长度的回文串,其根节点分别叫做“奇根”和“偶根”。普通边上有字母(类似trie/SAM的普通边,都是存\(\sum\)个外链,但是有一些是无......
  • 力扣2. 两数相加
    给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0 开头。 示例1:输入:l1=[2,4,3],l2=[5,6......
  • 力扣---1161. 最大层内元素和
    给你一个二叉树的根节点 root。设根节点位于二叉树的第1层,而根节点的子节点位于第2层,依此类推。请返回层内元素之和最大的那几层(可能只有一层)的层号,并返回其中 最小的那个。 示例1:输入:root=[1,7,0,7,-8,null,null]输出:2解释:第1层各元素之和为1,第2层各元素......
  • 回文数
    ```#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#defineN10voidmain(){   intn[N];   inti,j,k,s=0,flag,a;   for(i=0;i<=256;i++)   {       a=i*i;flag=1;s=1;       for(j=10;a/j!=0;s......
  • response返回文件给前端
    @GetMapping("/getPdf2")publicvoidgetPdf2(HttpServletResponseresponse)throwsIOException{Filefile=newFile("D://aasd.pdf");FileInputStreamfileInputStream=newFileInputStream(file);ServletOu......
  • 力扣---1080. 根到叶路径上的不足节点
    给你二叉树的根节点root和一个整数limit,请你同时删除树中所有不足节点,并返回最终二叉树的根节点。假如通过节点node的每种可能的“根-叶”路径上值的总和全都小于给定的limit,则该节点被称之为不足节点,需要被删除。叶子节点,就是没有子节点的节点。 示例1:输入:r......
  • 力扣---236. 二叉树的最近公共祖先
    给定一个二叉树,找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树T的两个节点p、q,最近公共祖先表示为一个节点x,满足x是p、q的祖先且x的深度尽可能大(一个节点也可以是它自己的祖先)。” 示例1:输入:root=[3,5,1,6,2,0,8,null,n......
  • 力扣---1372. 二叉树中的最长交错路径
    给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:选择二叉树中任意 节点和一个方向(左或者右)。如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。改变前进方向:左变右或者右变左。重复第二步和第三步,直到你在树中无法继续移动。交错路径的长度......
  • abc242E 求解小于等于一个字符串的回文串的个数
    题目链接:E-(∀x∀)考虑26进制,将字母A~Z折算成数字0~25,求得最大的可能的回文字符串的26进制值即为答案//>>>Qiansui#include<map>#include<set>#include<stack>#include<cmath>#include<queue>#include<deque>#include<cstdio>#include<string&......
  • 3.4 回文数
    打印所有不超过n(取n<256)的其平方具有对称性质的数(也称回文数)。 #include<stdio.h>voidmain(){intm[16],n,i,t,count=0;longunsigneda,k;printf("No.numberit'ssguare(palindrome)An");for(n=1;n<256;n++)/*穷举n的取值范围*/k-0;t-1;a=n*n;/*计算n的平......