## # 44. Wildcard Matching

Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-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 = "*"
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:
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
``````

### # Solution

Approach 1: DP.

Approach 2: greedy -- match greedily until we meet a star, then anchor that on both s and p to be able to get back to them. Running time `O(MN)`.

Approach 3: (Memory Limit Exceeded) Recursion with hash table.

### # Code (Python)

Approach 1:

``````    def isMatch(self, s: str, p: str) -> bool:
# match[i][j] -- s[:i] matches p[:j]
# if p[j-1] is *, then match[i][j] = match[i][j-1] or match[i-1][j]
match = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
match = True
for j in range(1, len(p) + 1):
if p[j-1] == '*' and match[j-1]:
match[j] = True

for i in range(1, len(s) + 1):
for j in range(1, len(p) + 1):
if p[j-1] == '?':
match[i][j] = True if match[i-1][j-1] else False
elif p[j-1] == '*':
match[i][j] = True if match[i][j-1] or match[i-1][j] else False
else:
match[i][j] = True if match[i-1][j-1] and p[j-1] == s[i-1] else False

return match[-1][-1]
``````

Approach 2:

``````    def isMatch(self, string: str, pattern: str) -> bool:
# http://chaoren.is-programmer.com/posts/42771.html
# idea: match greedily until we meet a star, then anchor that on both s and p to be able to get back to them
# running time O(MN), e.g. string = aaaaaaaa, pattern = *aaaab

# pointers at the string/pattern
s, p = 0, 0
# record the location that a star matches up to
matched_s, star_location = 0, -1

# exhaust the string
while s < len(string):
# p < len(pattern) is important in case we run out of the pattern
if p < len(pattern) and (string[s] == pattern[p] or pattern[p] == '?'):
s += 1
p += 1
# anchor down the matched parts when we first meet a start
elif p < len(pattern) and pattern[p] == '*':
matched_s = s
star_location = p
elif star_location == -1:
return False
else:
# drag points s and p back to match the start with 1 more char of string
matched_s += 1
s = matched_s
p = star_location + 1

# then exhaust the pattern
while p < len(pattern) and pattern[p] == '*':
p += 1

return p == len(pattern)
``````

### # Code (C++)

Approach 1:

``````// DP.
class Solution {
public:
bool isMatch(string s, string p) {
int sSize = s.size();
int pSize = p.size();
bool match[sSize+1][pSize+1];
match[sSize][pSize] = true;
for (int i = 0; i < sSize; ++i)
{
match[i][pSize] = false;
}
for (int i = pSize - 1; i >= 0; --i)
{
match[sSize][i] = (p[i] == '*') && match[sSize][i+1];
}
for (int i = sSize - 1; i >= 0; --i)
{
for (int j = pSize - 1; j >= 0; --j)
{
if (p[j] == '*')
match[i][j] = match[i][j+1] || match[i+1][j];
else
match[i][j] = (p[j] == '?' || p[j] == s[i]) &&
match[i+1][j+1];
}
}
return match;
}
};
``````

Approach 2:

``````// Greedy.
class Solution {
public:
bool isMatch(string s, string p) {
int sSize = s.size();
int pSize = p.size();
int sAnchor = -1;
int pAnchor = -1;
{
{
}
{
}
else if (pAnchor < 0)
{
return false;
}
else
{
}
}
{
return false;
}
return true;
}
};
``````

Approach 3:

``````// Memory Limit Exceeded.
class Solution {
private:
unordered_map<string,bool> umap;
public:
bool isMatch(string s, string p) {
string key = s + "," + p;
if (umap.find(key) != umap.end())
return umap[key];
bool match = false;
if (p.size() == 0)
{
match = s.size() == 0;
}
else if (p == '*')
{
match = isMatch(s, p.substr(1)) ||
s.size() > 0 && isMatch(s.substr(1), p);
}
else
{
match = s.size() > 0 && (p == '?' || p == s) &&
isMatch(s.substr(1), p.substr(1));
}
umap[key] = match;
return match;
}
};
``````