LeetCode 010 Regular Expression Matching
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 lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*
.
Example 1:
**Input:** s = "aa" p = "a" **Output:** false **Explanation:** "a" does not match the entire string "aa".
Example 2:
**Input:** s = "aa" p = "a*" **Output:** true **Explanation:** '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
**Input:** s = "ab" p = ".*" **Output:** true **Explanation:** ".*" means "zero or more (*) of any character (.)".
Example 4:
**Input:** s = "aab" p = "c*a*b" **Output:** true **Explanation:** c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".
Example 5:
**Input:** s = "mississippi" p = "mis*is*p*." **Output:** false
题目大意:
这道求正则表达式匹配的题和那道Leetocde 044 Wildcard Matching很类似,不同点在于*的意义不同,在之前那道题中,
*表示可以代替任意个数的不同字符,而这道题中的*表示之前一个字符(同样字符)可以有0-N个匹配。此题更难一些。
解题思路:
这是经典题。两字符串匹配题基本就是DP而且知道子问题答案可以推导下一个。
- 定义dp[i][j]为字符串s[i-1]和p[j-1]是否能匹配。
- 递归式为dp[i][j] = dp[i-1][j-1] && (p[j-1] == . || s[i-1] == p[j-1])
OR ((dp[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == .)) || dp[i][j-2]) && p[j-1] == *
第一种情况为非*,通配一样字符或.
第二种情况为*,如果通配(有条件:与p的前一个字符相等或p为.)就是只移动s,dp[i-1][j]。若不通配就只移动p及其前一个字符。 - 方向为从左到右,从上到下。初始值为dp[0][0] = true。以及若s为空,p为多个*时候,dp[0][j]=true。
与Wildcard Matching不同之处用黑体标注了:
- 用.代替?
- *情况,不匹配p移动两位而不是一位。
- *情况,匹配带条件而不是无条件。
- 初始化用dp[0][j-2]而不是j-1。
注意事项:
- 递归式含*不匹配情况dp[i][j-2]。
- 初始化s为空,p为多个*。此情况其实与递归式符合,因为i=1开始,所以i=0的时候,dp[i-1][j]为负值省去,
只取dp[i][j-2]。 - 循环中j按理应该从2开始,因为递归式含p[j-2], 这样要初始化第1列(第0列已经初始化为False)。由于题目条件保证星号前一定有其他字符,所以p的第0位不能是星号,所以j可以从1开始
- Python中任何矩阵初始化都只能用两重for循环而不能用乘号
Python代码:
1 | def isMatch(self, s: str, p: str) -> bool: |
Java代码:
1 | public boolean isMatch(String s, String p) { |
算法分析:
时间复杂度为O(n*m)
,空间复杂度为O(n*m)
。