边工作边刷题:70天一遍leetcode: day 39
Regular Expression Matching及变形
要点
fb的常考题, uber也考过。
思路: recursion是基本的结构: 假设s为待匹配string, p为pattern. 当前要匹配si和pi位置的char. 因为有的存在, 自然分成两种case: 就是有和没有. 如果不是, 只比较当前2个字符. 如果遇到*, 需要loop si当前位置所有向右(recursion)或者向左(dp)的相同char. 每一个会产生一个新的递归分支. 注意skip当前字符也是一个分支.
recursion:
base condition: 因为递归是向右, 所以如果pi超过pattern, 递归结束.
因为是和左边的字符关联的, 递归向右的情况, 其条件是p[pi+1]==''.
worst case: s: aa…aab, p: a…a: 每一层都要loop所有s中的a,loop中的每一个进入一个同样loop的层,形成一个tree structure,所以是O(2^n),space是O(n)
dp:
base condition: p向右移动
以当前字符是否为*作为条件
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
dp = [[False for j in range(len(p)+1)] for i in range(len(s)+1)]
dp[0][0] = True
for i in range(len(s)+1):
for j in range(1, len(p)+1):
if p[j-1]!='*':
if i==0: dp[i][j]=False
else:
dp[i][j]=(s[i-1]==p[j-1] or p[j-1]=='.') and dp[i-1][j-1]
else:
dp[i][j]=dp[i][j-2]
ii = i
while ii>0 and (s[ii-1]==p[j-2] or p[j-2]=='.'):
if dp[ii-1][j-2]:
dp[i][j]=True
break
ii-=1
return dp[len(s)][len(p)]