题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
思路:
本题就是很直观的字符串的匹配,难点在于当遇到模式中两个特殊字符怎么处理和对于各种形式字符串的全面考虑。这里采用递归的方式,每次只匹配s中一个字符(模式串pattern, 被匹配字符串s):
处理判断过程如下:
-
如果 s和pattern都为空,匹配成功
-
如果pattern是空串,而s不是,匹配失败
-
如果s,pattern均不是空串(长度至少为1),考虑到pattern中
*
前字符可以出现0次,所以不能简单比较s和pattern的第一个字符是否相等,这里分为两种情况考虑:- 如果pattern的第二个字符是
*
:- 如果s与pattern的第一个字符匹配(即s与pattern的第一个字符相等或者pattern第一个字符为
.
),剩余部分有三种匹配方式:(1)aaa
和 a*
a 这种情况, 星号代表了多个a, 因此s需要不断右移一位继续比较;(2)a
和a*a
中这情况, 这时候星号代表0个a, 因此s不需要右移, pattern需要右移两位;(3)abc
和a*bc
这种情况, 星号代表了1个a, s右移一位, pattern右移两位继续比较。 - 否则模式串pattern后移两位,相当于认为
*
前的字符在s中出现了0次;
- 如果s与pattern的第一个字符匹配(即s与pattern的第一个字符相等或者pattern第一个字符为
- 如果pattern的第二个字符不是
*
:如果s与pattern的第一个字符匹配(含义同上),s和pattern同时后移一位,继续匹配;否则匹配失败
- 如果pattern的第二个字符是
My Answer:
# -*- coding:utf-8 -*-
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
# write code here
if len(s) == 0 and len(pattern) == 0:
return True
if len(s) > 0 and len(pattern) == 0:
return False
# 如果模式的第二个字符是*
if len(pattern) > 1 and pattern[1] == '*':
if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
return self.match(s, pattern[2:]) or self.match(s[1:], pattern) or self.match(s[1:], pattern[2:])
else:
return self.match(s, pattern[2:])
else:
if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
return self.match(s[1:], pattern[1:])
else:
return False
参考答案:
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
# write code here
if len(s) == 0 and len(pattern) == 0:
return True
if len(s) > 0 and len(pattern) == 0:
return False
# 如果模式第二个字符是*
if len(pattern) > 1 and pattern[1] == '*':
if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
# 如果第一个字符匹配,三种可能1、模式后移两位;2、字符串移1位
return self.match(s, pattern[2:]) or self.match(s[1:], pattern)
else:
# 如果第一个字符不匹配,模式往后移2位,相当于忽略x*
return self.match(s, pattern[2:])
# 如果模式第二个字符不是*
if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
return self.match(s[1:], pattern[1:])
else:
return False
参考答案二:
# -*- coding:utf-8 -*-
class Solution:
# s, pattern都是字符串
def match(self, s, pattern):
# write code here
# 如果s和pattern匹配, 直接True
if s == pattern:
return True
# 如果pattern为'', 因为s和pattern不相等, 直接False
elif pattern == '':
return False
# 当s为'', 如果pattern为'.', 则返回True
# 当s为'', 如果pattern长度为1且不为'.', 或者pattern第二个字符不是*, 则pattern不可能为空, 返回False
# 若pattern长度不为1, 且第二个字符为*, pattern还有空的可能, 从第三个字符开始迭代
elif s == '':
if pattern == ".":
return False
elif len(pattern) == 1 or pattern[1] != '*':
return False
else:
return self.match(s, pattern[2:])
# 如果pattern长度不小于二, 而且pattern的第二个字符不是*的情况下
# 当 pattern[0] 不等于s[0], 且不为 . 的时候, s和pattern必不相等
# 否则, s 和 pattern 都右移一位, 继续比较
if len(pattern) >= 2 and pattern[1] != '*':
if s[0] != pattern[0] and pattern[0] != '.':
return False
else:
return self.match(s[1:], pattern[1:])
# 如果pattern长度不小于2, 且pattern第二个字符为*的情况下
# 如果s[0]不等于pattern[0], 且pattern[0]不为 . , 那么第一位比较不成功, pattern必须后移两位继续比较后面是否能和s第一位匹配
# 如果s[0]等于pattern[0], 或者pattern[0]为 . , 第一位匹配, 那么会有
# 1. aaa 和 a*a 这种情况, 星号代表了多个a, 因此s需要不断右移一位继续比较
# 2. a 和 a*a 中这情况, 这时候星号代表0个a, 因此s不需要右移, pattern需要右移两位
# 3. abc 和 a*bc 这种情况, 星号代表了1个a, s右移一位, pattern右移两位继续比较
elif len(pattern) >= 2 and pattern[1] == '*':
if s[0] != pattern[0] and pattern[0] != '.':
return self.match(s, pattern[2:])
else:
return self.match(s[1:], pattern) or self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:])
# 除去上述pattern不小于2情况, 只剩下pattern等于1的情况, 因此如果pattern为".", 而且s长度为1, 返回True
elif pattern == '.' and len(s) == 1:
return True
return False
Note:
-
Python 中的 sorted() 与 list.sort()区别:
对于一个无序的列表a,调用a.sort(),对a进行排序后返回a,sort()函数修改待排序的列表内容。
而对于同样一个无序的列表a,调用sorted(a),对a进行排序后返回一个新的列表,而对a不产生影响。
参考答案:
[1] https://blog.csdn.net/qq_20141867/article/details/80910724
[2] https://github.com/leeguandong/Interview-code-practice-python/blob/master/剑指offer/正则表达式匹配.py