leetcode 10
第十题挂了,时间超时,看了别人的想法
Given an input string (s
) and a pattern (p
), implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*
.
Example 1:
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input: s = "ab" p = ".*" Output: true Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input: s = "aab" p = "c*a*b" Output: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
Example 5:
Input: s = "mississippi" p = "mis*is*p*." Output: false
https://buptwc.github.io/2018/10/18/Leetcode-10-Regular-Expression-Matching/
https://www.cnblogs.com/grandyang/p/4461713.html
下面的是我原来的代码,想法就是首先如果p为空,那么只有s为空才正确;p为一位,那么不能为“*”,为“.”的时候,s可以是任意的字母,为通常字母时,s应为对应的字母;两位以上根据第二个字母是不是*再分类,代码如下
class Solution: def getLengthBeginSame(self, s, p): """ p是一个单字母或者".",s是一个字符串 求s开头有多少个重复的p """ length = 0 for i in s: if i == p or p == ".": length += 1 else: break return length def isMatch(self, s, p): """ :type s: str :type p: str :rtype: bool """ if len(p) == 0: return not s if p[0] == "*": return False if len(p) == 1: return len(s)==1 and (p == "." or p == s)
if p[1] == "*": len_beginsame = self.getLengthBeginSame(s, p[0]) for i in range(len_beginsame, -1, -1): if self.isMatch(s[i:], p[2:]): return True return False if len(s)>0 and (p[0] == s[0] or p[0] == "."): return self.isMatch(s[1:], p[1:]) return False
想了一想应该是犯了斐波拉契数列的相关算法题(跳楼梯,锯木头之类的)的问题,有很多重复计算,规划一下动态规划可能会好很多。
既然如此可以放一个集合来存储不成功的情况,因为我原来写的有成功的就直接true,所以只要存储不成功的情况,
假定集合中有元素(m,n),则表示s后m位和p后n位不匹配,只要在原来return False的地方之前加入集合即可,代码如下
class Solution: def __init__(self): #记载不匹配的集合,元素是元组,(m,n):表示s后m位和p后n位不匹配 self.set_notmatch = set() def getLengthBeginSame(self, s, p): """ p是一个单字母,s是一个字符串 求s开头有多少个重复的p """ length = 0 for i in s: if i == p or p == ".": length += 1 else: break return length def isMatch(self, s, p): """ :type s: str :type p: str :rtype: bool """ len_s = len(s) len_p = len(p) if (len_s, len_p) in self.set_notmatch: return False if not p: if not s: return True self.set_notmatch.add((len_s, len_p)) return False if p[0] == "*": return False if len_p == 1: if len_s == 1 and (p == "." or p == s): return True self.set_notmatch.add((len_s, len_p)) return False if p[1] == "*": len_beginsame = self.getLengthBeginSame(s, p[0]) for i in range(len_beginsame, -1, -1): if (len_s-i, len_p-2) in self.set_notmatch: continue if self.isMatch(s[i:], p[2:]): return True # self.set_notmatch.add((len_s - i, len_p - 2)) self.set_notmatch.add((len_s, len_p)) return False if len(s)>0 and (p[0] == s[0] or p[0] == "."): if (len_s-1, len_p-1) in self.set_notmatch: return False return self.isMatch(s[1:], p[1:]) return False if __name__ == "__main__": classa = Solution() # s = "aaaaabaccbbccababa" # p = "a*b*.*c*c*.*.*.*c" s = "abca" p = "a*ab*bc*ca*as*b*a" print(classa.isMatch(s, p)) print(classa.set_notmatch) # print(classa.getLengthBeginSame("aba", p[1]))
这下过了,
不过也可以放一个二维列表来存储成功与否的情况,没有很多次的迭代,不知道是否会快一点