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'.
Constraints:
0 <= s.length, p.length <= 2000
s contains only lowercase English letters.
p contains only lowercase English letters, '?' or '*'.
Solutions
Solution 1: Memoization Search
We design a function \(dfs(i, j)\), which represents whether the string \(s\) starting from the \(i\)-th character matches the string \(p\) starting from the \(j\)-th character. The answer is \(dfs(0, 0)\).
The execution process of the function \(dfs(i, j)\) is as follows:
If \(i \geq \textit{len}(s)\), then \(dfs(i, j)\) is true only when \(j \geq \textit{len}(p)\) or \(p[j] = '*'\) and \(dfs(i, j + 1)\) is true.
If \(j \geq \textit{len}(p)\), then \(dfs(i, j)\) is false.
If \(p[j] = '*'\), then \(dfs(i, j)\) is true if and only if \(dfs(i + 1, j)\) or \(dfs(i + 1, j + 1)\) or \(dfs(i, j + 1)\) is true.
Otherwise, \(dfs(i, j)\) is true if and only if \(p[j] = '?'\) or \(s[i] = p[j]\) and \(dfs(i + 1, j + 1)\) is true.
To avoid repeated calculations, we use the method of memoization search and store the result of \(dfs(i, j)\) in a hash table.
The time complexity is \(O(m \times n)\), and the space complexity is \(O(m \times n)\). Where \(m\) and \(n\) are the lengths of the strings \(s\) and \(p\), respectively.
We can convert the memoization search in Solution 1 into dynamic programming.
Define \(f[i][j]\) to represent whether the first \(i\) characters of string \(s\) match the first \(j\) characters of string \(p\). Initially, \(f[0][0] = \textit{true}\), indicating that two empty strings are matching. For \(j \in [1, n]\), if \(p[j-1] = '*'\), then \(f[0][j] = f[0][j-1]\).
Next, we consider the case of \(i \in [1, m]\) and \(j \in [1, n]\):
If \(p[j-1] = '*'\), then \(f[i][j] = f[i-1][j] \lor f[i][j-1] \lor f[i-1][j-1]\).
The time complexity is \(O(m \times n)\), and the space complexity is \(O(m \times n)\). Where \(m\) and \(n\) are the lengths of the strings \(s\) and \(p\), respectively.