题目描述
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]