题目: 正则表示匹配
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.
示例:
Input1: s = "aa" p = "a" Output1: false Explanation: "a" does not match the entire string "aa".Input2: s = "aa" p = "a*" Output2: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".Input3: s = "ab" p = ".*" Output3: true Explanation: ".*" means "zero or more (*) of any character (.)".Input4: s = "aab" p = "c*a*b" Output4: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".Input5: s = "mississippi" p = "mis*is*p*." Output5: false
首先在题目理解上,与之前的题(剑指offer)上的不同,“.* " 表示意义上可为任意数,而不一定是单一个数重复,见 input3。
其次,我们分析题意,可以分成以下几种情况:
1. s 为空,且p为空,表示同时结束,return True;
2. s为空,但p不为空,若想匹配成功,p必然为 “x*” 这类组合,*表示字符 x 个数为0;
3. s不为空,p为空,必然匹配不成功, return False;
4. s不为空,p不为空:
如果p[1] 不等于 “*”,看p[0]和s[0]是否匹配,如果字符相等,或p[0]为 “.”,则后移继续匹配,否则返回False;
如果p[1] 等于 "*", 则表示p[0]可以有0-N个,情况更为复杂一些,还需要看 p[0] 和 s[0] 是否匹配,若不匹配,必为0个,则 p 后移两位; 如果匹配,则说明当前s[0] 匹配成功,将s后移一位,剩余的继续判断。
上述逻辑,就是简单的递归,在写代码时,注意精简即可:
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
if not p:
return not s
first_match = bool(s) and p[0] in {"." , s[0]}
if len(p)>=2 and p[1]=="*":
return self.isMatch(s,p[2:]) or first_match and self.isMatch(s[1:],p)
else:
return first_match and self.isMatch(s[1:],p[1:])
递归方法十分耗时(≈1460ms),所以我们进一步考虑使用动态规划,以空间换时间。思路是一样的,增加了二维数组,存储已经计算的变量,从而极大减少了时间(时间 36 ms)。
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
saved = {}
def dp(i,j):
if (i,j) not in saved:
if j == len(p):
ans = (i == len(s))
else:
first_match = i <len(s) and p[j] in {".",s[i]}
if j+1 < len(p) and p[j+1] =="*":
ans = dp(i,j+2) or first_match and dp(i+1,j)
else:
ans = first_match and dp(i+1,j+1)
saved[i,j] = ans
return saved[i,j]
return dp(0,0)
小结:
本题主要难点在理清题目的主要思路,用最精简的方式写出代码。动态规划与递归方法都是基于题目的基本理解。