dfs 正则表达式
192. 通配符匹配
判断两个可能包含通配符“?”和“*”的字符串是否匹配。匹配规则如下:
- '?' 可以匹配任何单个字符。
- '*' 可以匹配任意字符串(包括空字符串)。
两个串完全匹配才算匹配成功。
样例
样例1
输入:
"aa"
"a"
输出: false
输出2
输入:
"aa"
"aa"
输出: true
输出3
输入:
"aaa"
"aa"
输出: false
输出4
输入:
"aa"
"*"
输出: true
说明: '*' 可以替换任何字符串
输出5
输入:
"aa"
"a*"
输出: true
样例6
输入:
"ab"
"?*"
输出: true
说明: '?' -> 'a' '*' -> 'b'
样例7
输入: "aab" "c*a*b" 输出: false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Solution: """ @param s: A string @param p: A string includes "?" and "*" @return: is Match? """ def isMatch( self , s, p): # write your code here self .cache = {} return self .helper(s, p, s_at = len (s) - 1 , p_at = len (p) - 1 ) def helper( self , s, p, s_at, p_at): if (s_at, p_at) in self .cache: return self .cache[(s_at, p_at)] if p_at < 0 : return s_at < 0 if s_at < 0 : for i in range ( 0 , p_at + 1 ): if p[i] ! = "*" : return False return True if p[p_at] = = '?' : is_match = self .helper(s, p, s_at - 1 , p_at - 1 ) elif p[p_at] = = '*' : is_match = self .helper(s, p, s_at - 1 , p_at) or \ self .helper(s, p, s_at, p_at - 1 ) else : is_match = s_at > = 0 and s[s_at] = = p[p_at] and \ self .helper(s, p, s_at - 1 , p_at - 1 ) self .cache[(s_at, p_at)] = is_match return is_match |
注意 如果不用cache的话会超时。
更复杂一点的题目:
154. 正则表达式匹配
实现支持'.'和'*'的正则表达式匹配。
'.'匹配任意一个字母。
'*'匹配零个或者多个前面的元素。
匹配应该覆盖整个输入字符串,而不仅仅是一部分。
需要实现的函数是:bool isMatch(string s, string 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
样例
样例 1:
输入:"aa","a"
输出:false
解释:
无法匹配
样例 2:
输入:"aa","a*"
输出:true
解释:
'*' 可以重复 a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | class Solution: """ @param s: A string @param p: A string includes "." and "*" @return: A boolean """ def isMatch( self , s, p): # write your code here self .cache = {} return self .helper(s, p, s_at = len (s) - 1 , p_at = len (p) - 1 ) def helper( self , s, p, s_at, p_at): if (s_at, p_at) in self .cache: return self .cache[(s_at, p_at)] if p_at < 0 : return s_at < 0 else : if s_at < 0 : for i in range (p_at, - 1 , - 2 ): if p[i] ! = '*' : return False return True if p[p_at] = = '.' : is_match = self .helper(s, p, s_at - 1 , p_at - 1 ) elif p[p_at] = = '*' : matched_once = (p_at > 0 and (p[p_at - 1 ] = = '.' or p[p_at - 1 ] = = s[s_at])) and \ self .helper(s, p, s_at - 1 , p_at) matched_none = self .helper(s, p, s_at, p_at - 2 ) is_match = matched_once or matched_none else : is_match = s_at > = 0 and s[s_at] = = p[p_at] and \ self .helper(s, p, s_at - 1 , p_at - 1 ) self .cache[(s_at, p_at)] = is_match return is_match |
算法思路整体上和上面题目一样,唯一的区别就是pattern -2,还有对于空串的匹配截止条件。
"" 匹配类似"a*b*c*"这样的模式。
当然,从前往后的匹配解法也是可以的,也就是匹配的时候pattern往前多看一步看是不是*来决定走一步还是走两步,参考代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | class Solution: """ @param s: A string @param p: A string includes "?" and "*" @return: is Match? """ def isMatch( self , source, pattern): return self .is_match_helper(source, 0 , pattern, 0 , {}) # source 从 i 开始的后缀能否匹配上 pattern 从 j 开始的后缀 # 能 return True def is_match_helper( self , source, i, pattern, j, memo): if (i, j) in memo: return memo[(i, j)] # source is empty if len (source) = = i: return self .is_empty(pattern[j:]) if len (pattern) = = j: return False if j + 1 < len (pattern) and pattern[j + 1 ] = = '*' : matched = self .is_match_char(source[i], pattern[j]) and self .is_match_helper(source, i + 1 , pattern, j, memo) or \ self .is_match_helper(source, i, pattern, j + 2 , memo) else : matched = self .is_match_char(source[i], pattern[j]) and \ self .is_match_helper(source, i + 1 , pattern, j + 1 , memo) memo[(i, j)] = matched return matched def is_match_char( self , s, p): return s = = p or p = = '.' def is_empty( self , pattern): if len (pattern) % 2 = = 1 : return False for i in range ( len (pattern) / / 2 ): if pattern[i * 2 + 1 ] ! = '*' : return False return True |
829. 字模式 II
给定一个pattern
和一个字符串str
,查找str
是否遵循相同的模式。
这里遵循的意思是一个完整的匹配,在一个字母的模式
和一个非空的单词str
之间有一个双向连接的模式对应。(如果a
对应s
,那么b
不对应s
。例如,给定的模式= "ab"
, str = "ss"
,返回false
)。
样例
样例1
输入:
pattern = "abab"
str = "redblueredblue"
输出: true
说明: "a"->"red","b"->"blue"
样例2
输入:
pattern = "aaaa"
str = "asdasdasdasd"
输出: true
说明: "a"->"asd"
样例3
输入:
pattern = "aabb"
str = "xyzabcxzyabc"
输出: false
注意事项
您可以假设模式
和str
只包含小写字母
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | class Solution: """ @param pattern: a string,denote pattern string @param str: a string, denote matching string @return: a boolean """ def wordPatternMatch( self , pattern, str ): # write your code here self .word_dict = {} self .word_match = {} return self .dfs(pattern, str ) def dfs( self , pattern, s): if not pattern: return not s if not s: return not pattern pattern_char = pattern[ 0 ] if pattern_char in self .word_dict: word_to_match = self .word_dict[pattern_char] return s[: len (word_to_match)] = = word_to_match and \ self .dfs(pattern[ 1 :], s[ len (word_to_match):]) else : for i in range ( 0 , len (s)): word = s[:i + 1 ] if word in self .word_match: continue self .word_dict[pattern_char] = word self .word_match[word] = pattern_char if self .dfs(pattern[ 1 :], s[i + 1 :]): return True del self .word_dict[pattern_char] del self .word_match[word] return False """ 这里我们为什么需要一个额外的 Set<String> 呢? 一个好的测试用例是: pattern: "bdpbibletwuwbvh" str: "aaaaaaaaaaaaaaa" 这里第一次执行时, map中匹配了 b -> a 递归进去以后第二次执行时,d 没有在 map 中,所以跳过了map的匹配检测, 所以进入循环体, 这时第二个word 又是 a, 按道理 a 应该被 b 匹配并且之前应该在map.containsKey的检查中跳出, 但现在并没有跳出,而是试图绑匹配给另一个pattern的字母 d, 很明显 b != d 重复绑定不是正确结果, 所以需要continue掉这次尝试。 """ |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2016-10-20 用 Spark 为 Elasticsearch 导入搜索数据