題目描述
Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
給定一個字符串 (s) 和一個字符模式 (p)。實現支持 '.' 和 '*' 的正則表達式匹配。
'.' 匹配任意單個字符。
'*' 匹配零個或多個前面的元素。
匹配應該覆蓋整個字符串 (s) ,而不是部分字符串。
說明:
s 可能為空,且只包含從 a-z 的小寫字母。
p 可能為空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。
解題思路
根據題意,給定兩個假設:
- * 不能出現在開頭
- 不能出現連續的*(兩個或多個)
基于動態規劃的解題思路:
matrix[i][j]表示s的前i個字符[0,i)組成的subString,與p的前j個字符[0,j)組成的subString的匹配結果,可以推斷,matrix[i][j]可以由已知的狀態推斷出未知的狀態
遞推矩陣的初始化
矩陣的大小應該是matrix[len(s)][len(p)]
- matrix[0][0]表示s和都是null,可以匹配,返回True
- s為非null,p是null,永遠不匹配,返回False
- s為null,p為非null時,需要分情況:如果沒有*,則一定不能匹配;
(注意:根據題意描述,我們推斷: *不能是第一個字符,同時,兩個以上*不能連續出現)
如果是*,matrix[0][n]結果與matrix[0][n-2]結果相同
代碼如下:
令matrix[i][j]表示s的前i個字符[0,i)組成的subString,與p的前j個字符[0,j)組成的subString的匹配結果
'''
matrix = [[False for i in range(n+1)] for i in range(m+1)]
'''
1、s和p都是null時,可以匹配,返回True
'''
matrix[0][0]=True
'''
2、 s為非null,p是null,永遠不匹配,返回False
3、 s為null,p為非null時,需要分情況:如果沒有*,則一定不能匹配;
(注意:根據題意描述,我推斷: *不能是第一個字符,同時,兩個以上*不能連續出現)
如果是*,matrix[0][n]結果與matrix[0][n-2]結果相同
'''
for i in range(2,n+1):
if(p[i-1] == '*'):
matrix[0][i] = matrix[0][i-2]
狀態轉移方程為:
- 如果s[i-1] == p[j-1] 或者 p[j-1] == "." 則: matrix[i][j] = matrix[i-1][j-1]
- 如果p[j-1] == "*" 則分2種情況:
?? 1. 如果 p[j-2] == s[i-1]或者p[j-2]=="."
???則 matrix[i][j] = {
????matrix[i][j-2] (此時表示前邊的字符出現0次)
????or matrix[i][j-1] (此時*表示前邊的字符出現1次)
????or matrix[i-1][j] (此時表示前邊的字符出現多次)
???}
?? 2. 如果 p[j-2]不是".",也不是s[i-1]
???則 matrix[i][j] = matrix[i][j-2]
完整python代碼
class Solution:
def isMatch(self, s: str, p: str) -> bool:
m = len(s)
n = len(p)
'''
初始化遞推矩陣
令matrix[i][j]表示s的前i個字符[0,i)組成的subString,與p的前j個字符[0,j)組成的subString的匹配結果
'''
matrix = [[False for i in range(n+1)] for i in range(m+1)]
'''
1、s和p都是null時,可以匹配,返回True
'''
matrix[0][0]=True
'''
2、 s為非null,p是null,永遠不匹配,返回False
3、 s為null,p為非null時,需要分情況:如果沒有*,則一定不能匹配;
(注意:根據題意描述,我推斷: *不能是第一個字符,同時,兩個以上*不能連續出現)
如果是*,matrix[0][n]結果與matrix[0][n-2]結果相同
'''
for i in range(2,n+1):
if(p[i-1] == '*'):
matrix[0][i] = matrix[0][i-2]
'''
狀態轉移公式:
令matrix[i][j]表示s的前i個字符[0,i)組成的subString,與p的前j個字符[0,j)組成的subString是否匹配,則
1、 如果s[i-1] == p[j-1] 或者 p[j-1] == "." 則: matrix[i][j] = matrix[i-1][j-1]
2、 如果p[j-1] == "*" 則分2種情況:
1)如果 p[j-2] == s[i-1]或者p[j-2]=="."
則 matrix[i][j] =( matrix[i][j-2](此時*表示前邊的字符出現0次)
or matrix[i][j-1](此時*表示前邊的字符出現1次)
or matrix[i-1][j](此時*表示前邊的字符出現多次) )
2)如果 p[j-2]不是".",也不是s[i-1]
則 matrix[i][j] = matrix[i][j-2]
'''
for i in range(1, m+1):
for j in range(1, n+1):
if( p[j-1]=="." or s[i-1] == p[j-1] ):
matrix[i][j] = matrix[i-1][j-1]
elif ( p[j-1] == "*" ):
if ( p[j-2]=="." or p[j-2]==s[i-1] ):
matrix[i][j] = ( matrix[i][j-1] or matrix[i][j-2] or matrix[i-1][j])
else :
matrix[i][j] = matrix[i][j-2]
return matrix[m][n]