leetcode string match相关题目
1. Regular Expression Matching(https://oj.leetcode.com/problems/regular-expression-matching/)
解法一:递归
(1)当p[j+1] != '*'时, 若s[i] == p[j] 或p[j]=='.', 返回isMatch(i+1, j+1)。 若s[i] != p[j], return False
(2)当p[j+1] == '*'时,若s[i] == p[j], 则要看s[i]开始的字串,若s[i],s[i+1]....s[k]都等于p[j],则要分别判断isMathc(i, j+2), isMatch(i+1, j+2), isMath(i+2, j+2)...isMatch(k, j+2),因为b*指的是0个或多个b
python代码如下:
1 def isMatch(self, s, p): 2 3 def match(idxs, idxp): 4 if idxp == len(p): 5 return idxs == len(s) 6 7 if idxp == len(p)-1 or p[idxp+1] != '*': 8 if idxs == len(s) or (s[idxs] != p[idxp] and p[idxp] != '.'): 9 return False 10 else: 11 return match(idxs+1, idxp+1) 12 else: 13 while idxs < len(s) and (s[idxs] == p[idxp] or p[idxp] == '.'): 14 if match(idxs, idxp+2): 15 return True 16 idxs += 1 17 return match(idxs, idxp+2) 18 19 return match(0, 0)
会TLE,最差情况是指数级的时间复杂度
解法二:动态规划
维护一个布尔数组res[i][j]来代表s的前i个字符和p的前j个字符是否匹配,这里res的维度是s.length+1, p.length+1。需要考虑一下三种情况:
(1)p[j+1] != '*', 若s[i] == p[j]并且res[i][j] == true, 则res[i+1][j+1] = true否则res[i+1][j+1]=false
(2)p[j+1] == '*', 若p[j] == '.', 则只要有res[i+1][j] == true 或 res[i+1][j-1] == true, 则res[i+1][j+1], res[i+2][j+1]..res[s.length][j+1]都为true
(3)p[j+1] == '*', 若p[j] != '.', 则若满足以下任意一条,res[i+1][j+1]即为true
(a) res[i+1][j-1] == true, ('*'前面一个字符都不取)
(b) res[i+1][j] == true( '*'前取一个字符)
(c) res[i][j+1] && s[i-1] == s[i] && s[i-1] = p[j-1](字符一直重复并且是'*'前面的那个字符)
1 def isMatch(self, s, p): 2 ls = len(s) 3 lp = len(p) 4 dp = [[False for i in range(lp+1)] for j in range(ls+1)] 5 6 dp[0][0] = True 7 for i in xrange(1, lp+1): 8 if p[i-1] == '*': 9 if i >= 2: 10 dp[0][i] = dp[0][i-2] 11 12 for i in xrange(1, ls+1): 13 for j in xrange(1, lp+1): 14 if p[j-1] == '.': 15 dp[i][j] = dp[i-1][j-1] 16 elif p[j-1] == '*': 17 dp[i][j] = dp[i][j-1] or dp[i][j-2] or (dp[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == '.')) 18 else: 19 dp[i][j] = dp[i-1][j-1] and s[i-1] == p[j-1] 20 21 return dp[ls][lp]
时间复杂度O(m*n), 空间复杂度O(m*n)
2.wildcard-matching(https://oj.leetcode.com/problems/wildcard-matching/)
解法一:
(1)若s[i] == p[j]或p[j] == '?', 匹配, i和j都向前移一位,即i++, j++
(2)若p[j] == '*', 匹配,记录此时'*'的位置以及匹配的s的位置
(3)其他情况,则不匹配
(a)判断之前是否出现过'*',若出现过,则将p的当前位置指向前一个'*'的位置的下一位,s的位置为之前记录位置的下一位,并且依然将此位置记录
(b)若未出现过'*',则返回false
(4)匹配到s末尾,若p仍然有剩余字符,判断剩余字符中如果仅存在'*'字符,返回True, 否则返回False
时间复杂度O(n)
1 def isMatch(self, s, p): 2 ls = len(s); lp = len(p) 3 currP = -1; currS = 0 4 idxs = 0; idxp = 0 5 while idxs < ls: 6 if idxp < lp and (s[idxs] == p[idxp] or p[idxp] == '?'): 7 idxs += 1; idxp += 1 8 continue 9 if idxp < lp and p[idxp] == '*': 10 currP = idxp; currS = idxs; idxp += 1 11 continue 12 if currP != -1: 13 idxp = currP + 1; currS += 1; idxs = currS 14 continue 15 return False 16 while idxp < lp: 17 if p[idxp] != '*': 18 return False 19 idxp += 1 20 return True