動態規劃問題示例

2021-10-02 15:31:58 字數 2433 閱讀 2255

給你乙個字串 s 和乙個字元規律 p,請你來實現乙個支援 '.' 和 '*' 的正規表示式匹配。

'.' 匹配任意單個字元

'*' 匹配零個或多個前面的那乙個元素

所謂匹配,是要涵蓋 整個 字串 s的,而不是部分字串。

說明s 可能為空,且只包含從 a-z 的小寫字母。

p 可能為空,且只包含從 a-z 的小寫字母,以及字元 . 和 *。

示例 1: 輸入:

s = "aa"

p = "a"

輸出: false

解釋: "a" 無法匹配 "aa" 整個字串。

示例 2: 輸入:

s = "aa"

p = "a*"

輸出: true

解釋: 因為 '*' 代表可以匹配零個或多個前面的那乙個元素, 在這裡前面的元素就是 'a'。因此,字串 "aa" 可被視為 'a' 重複了一次。

示例 3: 輸入:

s = "ab"

p = ".*"

輸出: true

解釋: ".*" 表示可匹配零個或多個('*')任意字元('.')。

示例 4: 輸入:

s = "aab"

p = "c*a*b"

輸出: true

解釋: 因為 '*' 表示零個或多個,這裡 'c' 為 0 個, 'a' 被重複一次。因此可以匹配字串 "aab"。

示例 5:輸入:

s = "mississippi"

p = "mis*is*p*."

輸出: false

解題思路: 按照動態規劃的標準流程解題。

狀態定義:

設動態規劃網格 dp, dp[i][j] ,dp[i][j] 代表字串 s 中前 i個字元和 p 中前 j個字元是否匹配,值為 true 或false

記 s 第 i個字元記為 s[m] == s[i - 1];p 第 j 個字元記為 p[n] == p[j - 1]

記 s 和 p 長度分別為 ls,lp

初始狀態:

初始化第一行:dp[0][j] = dp[0][j - 2] and p[j - 1] == '*';

tips: p 第 jj 個字元記為 '*'且 dp[0][j - 2]dp[0][j−2] 為 true

轉移方程:

當第 p[n]p[n] 為 '*'時:

當 p[n-1]p[n−1] 為 '.'或 s[m] == p[n-1] 時: dp[i][j] = dp[i-1][j]

tips: 此兩種情況代表 s[m]和 p[n-1]可以匹配,等價於無 s[m]的狀態 dp[i-1][j]

否則: dp[i][j] = dp[i][j-2]

tips: 此情況代表 s[m]和 p[n-1] 無法匹配,p[n-1] p[n]的組合必須出現 0 次,等價於沒有p[n−1] p[n]時的狀態 dp[i][j-2]

否則,當 p[n]為 '.'或 s[m] == p[n] 時: dp[i][j] = dp[i-1][j-1]

tips: 此情況代表 s[m]和 p[n]直接匹配,當前狀態等價於未匹配此兩字元前的狀態 dp[i-1][j-1]

返回值:

字串 s 中前 ls個字元和 p 中前 lp個字元是否匹配,即:dp[ls][lp]

複雜度分析:

時間複雜度 o(mn) 設 m, n分別為 s,p 長度,即為填充整個動態規劃網格 dp 所需時間。

空間複雜度 o(mn)動態規劃網格 dp占用 o(mn) 的額外空間。

def ismatch(self, s: str, p: str) -> bool:

ls, lp = len(s), len(p)

# 構造乙個 (lp+1) * (ls+1) 的 false矩陣

dp = [[false for _ in range(lp + 1)] for _ in range(ls + 1)]

dp[0][0] = true

for j in range(2, lp + 1):

dp[0][j] = dp[0][j - 2] and p[j - 1] == '*'

for i in range(1, ls + 1):

for j in range(1, lp + 1):

m, n = i - 1, j - 1

if p[n] == '*':

if s[m] == p[n - 1] or p[n - 1] == '.':

dp[i][j] = dp[i][j - 2] or dp[i - 1][j]

else:

dp[i][j] = dp[i][j - 2]

elif s[m] == p[n] or p[n] == '.':

dp[i][j] = dp[i - 1][j - 1]

return dp[-1][-1]

動態規劃示例二

求陣列的最大非遞減序列的長度。具體的講解請參看上篇給出的鏈結。include include maxincrementsublistlength求陣列的最大非遞減子串行的長度,輸入引數分別為陣列名和陣列長度 int maxincrementsublistlength int a,int arrayl...

動態規劃問題

思想 如果乙個問題是由交疊的子問題所構成,那麼我們就可以用動態規劃技術來解決它。一般來說,這樣的子問題出現在對給定問題求解的遞迴關係中。這個遞推關係包含了相 同問題的更小子問題的解。動態規劃法建議,與其對交疊子問題一次又一次的求解,不如把每個較小子問題只求解一次並把結果記錄在表中。例題 0 1揹包問...

動態規劃問題

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 ctest有n個蘋果,要將它放入容量為v的揹包。給出第i個蘋果的大小和價錢,求出能放入揹包的蘋果的總價錢最大值。輸入 有多組測試資料,每組測試資料第一行為2個正整數,分別代表蘋果的個數n和揹包的容量v,n v同時為0時結束測試,...