Sponsored
Sponsored
The dynamic programming approach uses a 2D table to store results of subproblems. We define dp[i][j] as True if the first i characters in the string s can be matched by the first j characters of the pattern p.
Base Cases:
Fill the table using the following rules:
Time Complexity: O(m*n) where m and n are the lengths of s and p, respectively.
Space Complexity: O(m*n) due to the storage of the dp table.
1public class Solution {
2 public bool IsMatch(string s, string p) {
3 int m = s.Length;
4 int n = p.Length;
5 bool[,] dp = new bool[m + 1, n + 1];
6 dp[0, 0] = true;
7
8 for (int j = 1; j <= n; j++) {
9 if (p[j - 1] == '*') {
10 dp[0, j] = dp[0, j - 1];
11 }
12 }
13
14 for (int i = 1; i <= m; i++) {
15 for (int j = 1; j <= n; j++) {
16 if (p[j - 1] == '*') {
17 dp[i, j] = dp[i - 1, j] || dp[i, j - 1];
18 } else {
19 dp[i, j] = dp[i - 1, j - 1] && (p[j - 1] == '?' || s[i - 1] == p[j - 1]);
20 }
21 }
22 }
23
24 return dp[m, n];
25 }
26}
27This C# code leverages a boolean matrix to track match relations. The loop structure reflects similar logic to the C++ and Java implementations for checking wildcard constraints.
The greedy algorithm approach tracks the position of the last '*' in the pattern and attempts to match remaining characters greedily. We maintain two pointers, one for the string and one for the pattern. When encountering '*', we remember the positions of both pointers in order to backtrack if needed.
If characters in p and s match or if the pattern has '?', both pointers are incremented. For '*', we shift the pattern pointer and remember indices for future potential matches. If there's a mismatch after '*', we use these remembered indices to backtrack.
Time Complexity: O(m + n) due to possible backtracking
Space Complexity: O(1) requiring constant storage for indices.
This greedy algorithm utilizes backtracking facilitated by the last seen '*' position to handle mismatches, allowing us to efficiently manage sequences that can contain many wildcard characters.