实现支持’.’和’*’的正则表达式匹配。
‘.’匹配任意一个字母。
‘*’匹配零个或者多个前面的元素。
匹配应该覆盖整个输入字符串,而不仅仅是一部分。
需要实现的函数是:bool isMatch(const char *s, const char *p)
样例
isMatch(“aa”,”a”) → false
isMatch(“aa”,”aa”) → true
isMatch(“aaa”,”aa”) → false
isMatch(“aa”, “a*”) → true
isMatch(“aa”, “.*”) → true
isMatch(“ab”, “.*”) → true
isMatch(“aab”, “c*a*b”) → true
和通配符匹配类似,遇到*的时候处理不同,这个如何处理搞了我好久。。。。很难受
同样是动态规划。
直接来看代码吧
class Solution:
"""
@param: s: A string
@param: p: A string includes "?" and "*"
@return: is Match?
"""
def isMatch(self, s, p):
# write your code here
m=len(s)
n=len(p)
dp=[[False]*(n+1) for x in range(m+1)]
dp[0][0]=True
for i in range(1,n+1):
#此处计算dp[0][j].当p中第j个字符是*时,看看把*去掉,或者把*之前的字符一块去掉,是否匹配。
if p[i-1]=='*':
if dp[0][i-1]==True or dp[0][i-2]==True:
dp[0][i]=True
for i in range(1,m+1):
for j in range(1,n+1):
if s[i-1]==p[j-1] or p[j-1]=='.':#相等或p中字符是‘.’,没什么说的。
dp[i][j]=dp[i-1][j-1]
elif p[j-1]=='*': # 如果p中字符是*:看下面文字吧
pre=p[j-2]
if pre!=s[i-1] and pre!='.':
dp[i][j]=dp[i][j-2]
else:
if dp[i][j-1]==True or dp[i][j-2]==True:#判断pre出现1次或0次能否匹配
dp[i][j]=True
else:
for k in range(1,i):
if dp[i-k][j-2]==True or dp[i-k][j-1]==True:
dp[i][j]=True
break
elif s[i-k]==s[i-k-1]:
continue
else:
break
#print dp
return dp[m][n]
如果p中字符是星号的话,用pre记录星号前面的字符。
1. 当pre不等于s中当前字符而且,pre也不是 点 的时候,那么无论这个pre重复1次还是几次,都匹配不上,只能是0次有可能匹配,所以dp[i][j]=dp[i][j-2]。
2. pre等于s中当前字符或者pre是 点 。那么首先判断 这个pre出现1次或者出现0次时是否能匹配。不能匹配的话,继续。pre出现2次以上,那么这就相当于在p串不变的情况下,从s串中的尾部连续删掉x个pre(注意这些删掉的字符必须相同,不相同的时候,就停止)。
这个 星号处理 有可能有重复的判断,但是应该是很少一部分。