-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlc0044_wildcard-matching.py
More file actions
147 lines (105 loc) · 3.64 KB
/
lc0044_wildcard-matching.py
File metadata and controls
147 lines (105 loc) · 3.64 KB
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
44. Wildcard Matching
Hard
Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*' where:
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).
Example 1:
Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa", p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input: s = "cb", p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input: s = "adceb", p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input: s = "acdcb", p = "a*c?b"
Output: false
Constraints:
0 <= s.length, p.length <= 2000
s contains only lowercase English letters.
p contains only lowercase English letters, '?' or '*'.
"""
from functools import lru_cache
"""
DP Recursive 动态规划
Note: * match empty or any chars (match any chars first seems faster)
time O(SP)
space O(SP)
"""
class Solution0:
def isMatch(self, s: str, p: str) -> bool:
@lru_cache(None)
def helper(s, p):
# print('s=%s p=%s' % (s, p))
if not s:
if not p or (p[0] == '*' and len(set(p)) == 1): # if s is empty, only match empty p or 1 or more *
return True
else:
return False
# s not empty
if not p:
return False
# both s and p not empty
if s[0] == p[0] or p[0] == '?': # single char match or ?
i, j = 0, 0
while i < len(s) and j < len(p) and (s[i] == p[j] or p[j] == '?'):
i += 1
j += 1
return helper(s[i:], p[i:])
elif p[0] == '*':
# * match any char or empty
return helper(s[1:], p) or helper(s, p[1:])
else: # no wild char, and s[0] != p[0]
return False
return helper(s, p)
"""
DP Two Series 双序列动态规划 bottom up
dp[i][j] := up to s[i-1] [j-1], is it match or not?
base case
dp[0][0] = True # empty matches empty
dp[0][j] = dp[0][j-1]|p[j-1]=='*' # * matches anything, including empty
transition:
if s[i-1] == p[j-1] or p[j-1] == '?':
dp[i][j] = dp[i-1][j-1]
elif p[j-1] == '*':
dp[i][j] = dp[i-1][j] # * matches anything
or dp[i][j-1] # * matches empty
time O(SP)
space O(SP)
"""
class Solution:
def isMatch(self, s: str, p: str) -> bool:
m, n = len(s), len(p)
dp = [[False for _ in range(n + 1)] for _ in range(m + 1)]
# base case
dp[0][0] = True # empty matches empty
for j in range(1, n + 1):
if p[j - 1] == '*': # * matches anything
dp[0][j] = dp[0][j - 1]
for i in range(1, m + 1):
for j in range(1, n + 1):
if p[j - 1] == '*':
dp[i][j] = dp[i - 1][j] or dp[i][j - 1]
elif s[i - 1] == p[j - 1] or p[j - 1] == '?':
dp[i][j] = dp[i - 1][j - 1]
# print(dp)
return dp[m][n]
def main():
sol = Solution()
assert sol.isMatch(s = "aa", p = "a") is False, 'fails'
assert sol.isMatch(s = "aa", p = "*") is True, 'fails'
assert sol.isMatch(s = "cb", p = "?a") is False, 'fails'
assert sol.isMatch(s = "adceb", p = "*a*b") is True, 'fails'
assert sol.isMatch(s = "acdcb", p = "a*c?b") is False, 'fails'
if __name__ == '__main__':
main()