题目介绍
请实现一个函数用来匹配包括 . 和 * 的正则表达式。
模式中的字符 . 表示任意一个字符,而 * 表示它前面的字符可以出现任意次(包含0次)。
在本题中,匹配是指字符串的所有字符匹配整个模式。
字符串"aaa"与模式"a.a"和"ab*ac*a"匹配;
字符串"aaa"与"aa.a"和"ab*a"均不匹配。
题目解读
我们可以先从 * 字符进行入手,因为 * 字符相对于 . 字符来说较为复杂,情况也更多。
首先按第一个字符后是否为 * 字符,分为两种情况,再对这两种情况进行讨论。
1.首字符后(也就是第二个字符)为 * 字符时,这种情况下我们会再进行一次判断:
判断字符串和pattern的首字符是否相等,如果不相等,我们只有将pattern后移两个字符,才有匹配成功的可能;
如果首字符相等 ( . 也可以看作相等),那么又会有以下三种匹配模式:
- 直接跳过pattern的前两个字符,也就是 * 前面的字符看作出现0次;
- 字符串后移一个字符,pattern后移两个字符,即将 * 前面出现的字符看作出现一次;
- 字符串后移一个字符,pattern保持不动,即将 * 前面的字符看作出现多次;
结合下面四个例子,会看得比较清晰:
字符串为“aabb”
pattern1: c*aabb 首字符不相等,只能将pattern后移两个字符;
pattern2: a*aabb 此时首字符虽然相等,但也需要把 * 前面的字符看作出现0次,才能匹配成功;
pattern3: a*abb 首字符相等,把 * 前面的字符看作出现1次,进行正常匹配;
pattern4: a*bb 首字符相等,但这时需要把 * 前面的字符看作出现多次(2次及以上),才能进行匹配。
以上4种情况,只要到最后任一匹配成功,就返回True。
2.首字符后(也就是第二个字符)不为 * 字符时,我们就可以直接比较字符串和pattern两个首字符:
- 若相等,两者都后移一个字符,进行下一轮比较;
- 若不等,可直接返回False。
字符串为“abcd”
pattern1: abcd 首字符都为a,判断下一个字符;
pattern2: bbcd 首字符不相等,直接返回False。
代码解析
def match(self, s, pattern):
# 递归终止条件
if s == pattern: return True
if not pattern: return False
# 判断第二个字符是否为 *
if len(pattern)>1 and pattern[1] == '*':
# 判断首字符是否相等,不要忘记 . 的情况
if s and (pattern[0] == s[0] or pattern[0] == '.'):
# 相等的情况下,三种匹配模式
return self.match(s[1:],pattern[2:]) \
or self.match(s,pattern[2:]) \
or self.match(s[1:], pattern)
else:
# 不等时,只能将pattern后移,继续判断
return self.match(s, pattern[2:])
# 第二个字符不为 *,直接对首字符进行比较
elif s and (s[0] == pattern[0] or pattern[0] == '.'):
return self.match(s[1:], pattern[1:])
return False