We use Dynamic Programming. dp[i][j] represents whether s[i:] matches p[j:].
- Use recursion with memoization (top-down DP).
- Base Case: If
pis empty, returnTrueifsis also empty. - First Match: Check if
s[0]matchesp[0](including.case). - If
p[1] == '*':- Case 1: Ignore
*and preceding (zero occurrence):match(s, p[2:]). - Case 2: Use
*once (if first match exists):first_match and match(s[1:], p).
- Case 1: Ignore
- Else: Return
first_match and match(s[1:], p[1:]).
- Time Complexity: O(N * M).
- Space Complexity: O(N * M).
def is_match(s, p):
memo = {}
def dp(i, j):
if (i, j) in memo: return memo[(i, j)]
if j == len(p): return i == len(s)
first_match = i < len(s) and p[j] in {s[i], '.'}
if j + 1 < len(p) and p[j + 1] == '*':
ans = (dp(i, j + 2) or
(first_match and dp(i + 1, j)))
else:
ans = first_match and dp(i + 1, j + 1)
memo[(i, j)] = ans
return ans
return dp(0, 0)