【LeetCode】647. 回文子串

问题描述

Given a string, your task is to count how many palindromic substrings in this string.

The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.

Note:

  1. The input string length won't exceed 1000.

给定一个字符串,您的任务是计算该字符串中有多少回文子字符串。
具有不同起始索引或结束索引的子字符串被视为不同的子字符串,即使它们由相同的字符组成。

注意:
输入字符串长度不会超过1000。

例子 1:
输入: "abc"
输出: 3
解释: "a", "b", "c".


例子 2:
输入: "aaa"
输出: 6
解释: "a", "a", "a", "aa", "aa", "aaa".

Python 实现

回文串的特点是:正序或者逆序读取该字符串的结果是相同的。因此,我们只要找到每个子串相应的中间位置,分别向两端拓展,去判断两端的字符是否相同,从而可以逐个找出题目所要求的回文子串。

题目规定,即便两个子串由相同字符组成,只要他们具有不同的起始或者结束索引,则被视为不同的子字符串。因此,我们不需要再去区分不同位置的相同子字符串了。

 

实现一:从中间位置进行拓展

从中间索引开始拓展,主要分两种情况:子字符串长度为奇数,以及子字符串长度为偶数。

class Solution(object):
	# Method 1.
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        
        cnt = 0
        for i in range(len(s)):
            # Odd length substrings.
            cnt += self.checkFromMid(s, i, i)
            # Even length substrings.
            cnt += self.checkFromMid(s, i, i+1)
        
        return cnt
    
    def checkFromMid(self, s, left, right):
        '''
            Left and right are the middle indices as starts. Check a substring whether a palindromic string or not from its middle.
        '''
        cnt = 0
        while left >= 0 and right < len(s) and s[left] == s[right]:
            # Two edge's char is the same.
            left -= 1
            right += 1
            cnt += 1
        return cnt

实现二:动态规划

正如前面所说,寻找子字符串可以从中间开始,依次向两端拓展。所以,我们可以根据前面找到的回文子串为基础,再判断分别从两端拓展一个长度后的子串是否为回文串即可。这就是这一题动态规划的基本思路。

我们先列举总共可能出现的几种情况:

  1. 长度为1的子字符串:必然为回文串;
  2. 长度为2的子字符串:当两个字符都相同时,则为回文串;
  3. 长度大于3的子字符串:当其去掉头尾字符的子字符串为回文串,且头尾两个字符相同时,则为回文串。

以条件1、2作为基础条件,再根据条件3动态解出其他情况时的判断结果。

class Solution(object):
	# Method 2: Dynamic Programming.
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """

        # Dynamic Programming.
        '''
            1. One-length substrings are always Palindromic Substrings.
            2. Two-length substrings are always not Palindromic Substrings due to different characters at the start and the end.
            3. Substrings whose lengths are over three are Palindromic Substrings only then their start and end characters are the same, and their substrings without the start and the end characters are still substrings.

            Therefore, the first two conditions can be used as a basic step, and then generate the third situation with the previous two results.
        '''

        length = len(s)

        # Input check.
        if length == 0:
            return 0
        if length == 1:
            return 1

        # Create a len(s) by len(s) arrays to record the result of each substring by locating on the start and the end indices.
        dp = [[False for j in range(length)] for i in range(length)]

        cnt = 0

        # ith row; jth col.
        for i in range(length):
            for j in range(i+1):
                # One-length substring.
                if i == j:
                    dp[i][j] = True
                    cnt += 1
                # Two-length substring.
                elif i == j+1 and s[i] == s[j]:
                    dp[i][j] = True
                    cnt += 1
                # Inner substring is Palindromic Substring and the others characters are the same.
                elif i > 0 and dp[i-1][j+1] and s[i] == s[j]:
                    dp[i][j] = True
                    cnt += 1
        return cnt

 

链接:https://leetcode.com/problems/palindromic-substrings/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,有三种方法可以解决LeetCode上的最长回文子串问题。 方法一是使用扩展中心法优化,即从左向右遍历字符串,找到连续相同字符组成的子串作为扩展中心,然后从该中心向左右扩展,找到最长的回文子串。这个方法的时间复杂度为O(n²)。\[1\] 方法二是直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串。这个方法的时间复杂度为O(n³),效率较低。\[2\] 方法三是双层for循环遍历所有子串可能,然后再对比是否反向和正向是一样的。这个方法的时间复杂度也为O(n³),效率较低。\[3\] 综上所述,方法一是解决LeetCode最长回文子串问题的最优解法。 #### 引用[.reference_title] - *1* [LeetCode_5_最长回文子串](https://blog.csdn.net/qq_38975553/article/details/109222153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode-最长回文子串](https://blog.csdn.net/duffon_ze/article/details/86691293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [LeetCode 第5题:最长回文子串(Python3解法)](https://blog.csdn.net/weixin_43490422/article/details/126479629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值