647. 回文子串

思路

先寫個(gè)暴力 對(duì)所有的左右邊界進(jìn)行枚舉 時(shí)間復(fù)雜度O(n^3)

class Solution:
    def countSubstrings(self, s: str) -> int:
        # 計(jì)數(shù)問題 
        # 1.定義狀態(tài) dp[i][j]=k表示包含i到j(luò)元素的回文串的個(gè)數(shù) 左閉右閉
        # 2.轉(zhuǎn)移方程 如果固定i dp[i][j] = dp[i][j-1]+dp[j][j]

    
        # 先寫個(gè)暴力
        def judge(i,j):
            while(j>=i):
                if not s[i]==s[j]:
                    return False
                i+=1
                j-=1
            return True

        s_len = len(s)
        res = 0
        for i in range(s_len):
            for j in range(i,s_len):
                if judge(i,j):
                    res+=1
        return res

反思

超時(shí) 暴力很明顯的一點(diǎn)是重疊的子問題太多了,有些是回文串的我們已經(jīng)判斷過了,明顯具有重疊子問題

優(yōu)化

dp! 三個(gè)步驟 定義狀態(tài) 轉(zhuǎn)移方程 基本情況
1.定義狀態(tài):由暴力法我們發(fā)現(xiàn) 重疊的子問題是子串是否是回文串
那么我們定義狀態(tài)為 dp[i][j]表示 i,j段的串是否是回文串 是則是1 不是則為0
2.狀態(tài)轉(zhuǎn)移:對(duì)于一個(gè)dp[i][j] 如果str[i]!=str[j] 直接是false 如果相等則需討論:
如果 i==j:單個(gè)字符肯定是回文的
如果 i+1==j:說明由倆個(gè)相同字符組成也是回文的
除以上倆種:規(guī)約成子問題 dp[i+1][j-1]是不是回文的
3.遍歷方向:為什么需要考慮遍歷方向? 因?yàn)槲覀兊臓顟B(tài)的轉(zhuǎn)移不是常規(guī)的[i-1][j-1] 而是 [i+1][j-1]
dp表如下
i,j-1 i,j
i+1,j-1 i+1,j+1
可以發(fā)現(xiàn)是從坐下推右上,并且我們假定右邊界大于等于左邊界 實(shí)際上只有dp表的上三角區(qū)域是有效的
4.基本情況:由2知i==j時(shí)都是true 即對(duì)角線上的都是True
至此 dp解法成立

實(shí)現(xiàn)

class Solution:
    def countSubstrings(self, s: str) -> int:
        # 計(jì)數(shù)問題 
        # 1.定義狀態(tài) dp[i][j]=1 or 0 表示包含i到j(luò)元素的左閉右閉串是否為回文串 是1 否0
        # 2.轉(zhuǎn)移方程 如果固定i dp[i][j] = dp[i][j-1]+dp[j][j] 
        # 狀態(tài)轉(zhuǎn)移:對(duì)于一個(gè)dp[i][j] 如果str[i]!=str[j] 直接是false 如果相等則需討論:
        # 如果 i==j:單個(gè)字符肯定是回文的
        # 如果 i+1==j:說明由倆個(gè)相同字符組成也是回文的
        # 除以上倆種:規(guī)約成子問題 dp[i+1][j-1]是不是回文的
        s_len = len(s)
        ans =0
        dp = [[0]*s_len for _ in range(s_len)]
        
        # # 基本情況
        # for i in range(s_len):
        #     dp[i][i]=1
        # print(dp)
        # 狀態(tài)轉(zhuǎn)移
        for i in range(s_len-1,-1,-1): # i 從大往小
            # print(i)
            for j in range(i,s_len): # j 從小往大
                if s[i]==s[j]:
                    if j-i<=1: # 處理單個(gè)和倆個(gè)的情況
                        dp[i][j] = 1
                        ans+=1
                    else:
                        dp[i][j]=dp[i+1][j-1]
                        if dp[i][j]==1:
                            ans+=1
                else:
                    dp[i][j]=0
        return ans
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 647.回文子串 給定一個(gè)字符串,你的任務(wù)是計(jì)算這個(gè)字符串中有多少個(gè)回文子串。具有不同開始位置或結(jié)束位置的子串,即...
    一角錢技術(shù)閱讀 242評(píng)論 0 0
  • 題目描述:給定一個(gè)字符串,你的任務(wù)是計(jì)算這個(gè)字符串中有多少個(gè)回文子串。具有不同開始位置或結(jié)束位置的子串,即使是由相...
    墨痕_UCAS閱讀 1,035評(píng)論 0 3
  • 題目 難度:★★★☆☆類型:數(shù)組方法:動(dòng)態(tài)規(guī)劃 力扣鏈接請(qǐng)移步本題傳送門[https://leetcode-cn....
    玖月晴閱讀 825評(píng)論 0 0
  • 5. 最長(zhǎng)回文子串 題目描述 給定一個(gè)字符串 s,找到 s 中最長(zhǎng)的回文子串。你可以假設(shè) s 的最大長(zhǎng)度為 100...
    greedycr7閱讀 278評(píng)論 0 0
  • title: 經(jīng)典算法問題:最長(zhǎng)回文子串之 Manacher 算法date: 2019-02-17 08:00:0...
    李威威閱讀 2,256評(píng)論 0 4

友情鏈接更多精彩內(nèi)容