|
1 | 1 | """
|
2 |
| -Given two strings, an input string and a pattern, |
3 |
| -this program checks if the input string matches the pattern. |
| 2 | +Author : ilyas dahhou |
| 3 | +Date : Oct 7, 2023 |
4 | 4 |
|
5 |
| -Example : |
6 |
| -input_string = "baaabab" |
7 |
| -pattern = "*****ba*****ab" |
8 |
| -Output: True |
| 5 | +Task: |
| 6 | +Given an input string and a pattern, implement wildcard pattern matching with support |
| 7 | +for '?' and '*' where: |
| 8 | +'?' matches any single character. |
| 9 | +'*' matches any sequence of characters (including the empty sequence). |
| 10 | +The matching should cover the entire input string (not partial). |
9 | 11 |
|
10 |
| -This problem can be solved using the concept of "DYNAMIC PROGRAMMING". |
11 |
| -
|
12 |
| -We create a 2D boolean matrix, where each entry match_matrix[i][j] is True |
13 |
| -if the first i characters in input_string match the first j characters |
14 |
| -of pattern. We initialize the first row and first column based on specific |
15 |
| -rules, then fill up the rest of the matrix using a bottom-up dynamic |
16 |
| -programming approach. |
17 |
| -
|
18 |
| -The amount of match that will be determined is equal to match_matrix[n][m] |
19 |
| -where n and m are lengths of the input_string and pattern respectively. |
| 12 | +Runtime complexity: O(m * n) |
20 | 13 |
|
| 14 | +The implementation was tested on the |
| 15 | +leetcode: https://leetcode.com/problems/wildcard-matching/ |
21 | 16 | """
|
22 | 17 |
|
23 | 18 |
|
24 |
| -def is_pattern_match(input_string: str, pattern: str) -> bool: |
| 19 | +def is_match(string: str, pattern: str) -> bool: |
25 | 20 | """
|
26 |
| - >>> is_pattern_match('baaabab','*****ba*****ba') |
| 21 | + >>> is_match("", "") |
| 22 | + True |
| 23 | + >>> is_match("aa", "a") |
27 | 24 | False
|
28 |
| - >>> is_pattern_match('baaabab','*****ba*****ab') |
| 25 | + >>> is_match("abc", "abc") |
| 26 | + True |
| 27 | + >>> is_match("abc", "*c") |
| 28 | + True |
| 29 | + >>> is_match("abc", "a*") |
29 | 30 | True
|
30 |
| - >>> is_pattern_match('aa','*') |
| 31 | + >>> is_match("abc", "*a*") |
| 32 | + True |
| 33 | + >>> is_match("abc", "?b?") |
| 34 | + True |
| 35 | + >>> is_match("abc", "*?") |
| 36 | + True |
| 37 | + >>> is_match("abc", "a*d") |
| 38 | + False |
| 39 | + >>> is_match("abc", "a*c?") |
| 40 | + False |
| 41 | + >>> is_match('baaabab','*****ba*****ba') |
| 42 | + False |
| 43 | + >>> is_match('baaabab','*****ba*****ab') |
| 44 | + True |
| 45 | + >>> is_match('aa','*') |
31 | 46 | True
|
32 | 47 | """
|
33 |
| - |
34 |
| - input_length = len(input_string) |
35 |
| - pattern_length = len(pattern) |
36 |
| - |
37 |
| - match_matrix = [[False] * (pattern_length + 1) for _ in range(input_length + 1)] |
38 |
| - |
39 |
| - match_matrix[0][0] = True |
40 |
| - |
41 |
| - for j in range(1, pattern_length + 1): |
42 |
| - if pattern[j - 1] == "*": |
43 |
| - match_matrix[0][j] = match_matrix[0][j - 1] |
44 |
| - |
45 |
| - for i in range(1, input_length + 1): |
46 |
| - for j in range(1, pattern_length + 1): |
47 |
| - if pattern[j - 1] in ("?", input_string[i - 1]): |
48 |
| - match_matrix[i][j] = match_matrix[i - 1][j - 1] |
| 48 | + dp = [[False] * (len(pattern) + 1) for _ in string + "1"] |
| 49 | + dp[0][0] = True |
| 50 | + # Fill in the first row |
| 51 | + for j, char in enumerate(pattern, 1): |
| 52 | + if char == "*": |
| 53 | + dp[0][j] = dp[0][j - 1] |
| 54 | + # Fill in the rest of the DP table |
| 55 | + for i, s_char in enumerate(string, 1): |
| 56 | + for j, p_char in enumerate(pattern, 1): |
| 57 | + if p_char in (s_char, "?"): |
| 58 | + dp[i][j] = dp[i - 1][j - 1] |
49 | 59 | elif pattern[j - 1] == "*":
|
50 |
| - match_matrix[i][j] = match_matrix[i - 1][j] or match_matrix[i][j - 1] |
51 |
| - else: |
52 |
| - match_matrix[i][j] = False |
53 |
| - |
54 |
| - return match_matrix[input_length][pattern_length] |
| 60 | + dp[i][j] = dp[i - 1][j] or dp[i][j - 1] |
| 61 | + return dp[len(string)][len(pattern)] |
55 | 62 |
|
56 | 63 |
|
57 | 64 | if __name__ == "__main__":
|
58 | 65 | import doctest
|
59 | 66 |
|
60 | 67 | doctest.testmod()
|
61 |
| - |
62 |
| - print(f"{is_pattern_match('baaabab','*****ba*****ab')}") |
| 68 | + print(f"{is_match('baaabab','*****ba*****ab') = }") |
0 commit comments