Skip to content

Commit

Permalink
Merge pull request #1117 from Rahul-Morabiya/B9
Browse files Browse the repository at this point in the history
Added Wildcard Matching Algorithm
  • Loading branch information
pankaj-bind authored Oct 23, 2024
2 parents 22e0f5d + fee56a2 commit 9d85e11
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
65 changes: 65 additions & 0 deletions Dynamic Programming/Wildcard Matching/Program.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

// Function to check if all characters in S1 are '*'
bool isAllStars(char *S1, int i) {
for (int j = 0; j < i; j++) {
if (S1[j] != '*')
return false;
}
return true;
}

// Function to check wildcard matching
bool wildcardMatching(char *S1, char *S2) {
int n = strlen(S1);
int m = strlen(S2);

// Previous and current row arrays for DP
bool prev[m + 1], cur[m + 1];

// Initialize the prev array (for i = 0)
prev[0] = true; // Empty pattern matches empty string
for (int j = 1; j <= m; j++) {
prev[j] = false; // Empty pattern doesn't match any non-empty string
}

// Loop over each character in S1
for (int i = 1; i <= n; i++) {
// Initialize cur[0] (matching an empty S2 with S1[0..i-1])
cur[0] = isAllStars(S1, i);

// Loop over each character in S2
for (int j = 1; j <= m; j++) {
if (S1[i - 1] == S2[j - 1] || S1[i - 1] == '?') {
cur[j] = prev[j - 1];
} else if (S1[i - 1] == '*') {
cur[j] = prev[j] || cur[j - 1];
} else {
cur[j] = false;
}
}

// Copy cur to prev for the next iteration
for (int j = 0; j <= m; j++) {
prev[j] = cur[j];
}
}

// Final result is in prev[m]
return prev[m];
}

int main() {
char S1[] = "a*?b";
char S2[] = "axxb";

if (wildcardMatching(S1, S2)) {
printf("The strings match!\n");
} else {
printf("The strings do not match.\n");
}

return 0;
}
85 changes: 85 additions & 0 deletions Dynamic Programming/Wildcard Matching/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Wildcard Matching

## Problem Statement

We are given two strings `S1` and `S2`. String `S1` may contain two special characters:
- `'?'` which can match **any single character** of `S2`.
- `'*'` which can match **any sequence of characters**, including an empty sequence from `S2`.

We need to check whether the two strings match or not, based on the rules of wildcard matching.

### Example

#### Example 1:
- **Input**:
`S1 = "a*?b"`,
`S2 = "axxb"`
- **Output**: `True`
- Explanation: The wildcard `*` can match `"xx"` and `?` can match `"x"`, making the entire string match.

#### Example 2:
- **Input**:
`S1 = "a*b"`,
`S2 = "acdfb"`
- **Output**: `True`
- Explanation: The `*` matches `"cdf"` and the rest of the characters align.

### Approach

We will solve the problem using **Dynamic Programming (DP)** with **space optimization** to reduce memory usage.

#### Key Insights:
- If we encounter a `?`, it must match exactly one character from `S2`.
- If we encounter a `*`, it can match any sequence of characters (including an empty string), which gives us two options:
- Consider the `*` as matching nothing (move to the next character in `S1`).
- Consider the `*` as matching one or more characters (move to the next character in `S2`).

#### DP Recurrence Relation:
- If `S1[i-1] == S2[j-1]` or `S1[i-1] == '?'`:
`dp[i][j] = dp[i-1][j-1]`

- If `S1[i-1] == '*'`:
`dp[i][j] = dp[i-1][j] || dp[i][j-1]`
- The first term `dp[i-1][j]` corresponds to skipping the `*` (considering it as an empty sequence).
- The second term `dp[i][j-1]` corresponds to the `*` matching one or more characters of `S2`.

### Space Optimization

Instead of maintaining a full 2D DP table, we can optimize space by only keeping track of the current and previous rows since each row in the DP table only depends on the previous row.

#### Steps:
1. Use two 1D arrays `prev` and `cur`:
- `prev[j]`: Stores results for the previous row.
- `cur[j]`: Stores results for the current row.

2. Initialize the `prev` array based on base cases, where matching an empty string (`S1 == ""`) against `S2` will depend on whether `S1` contains only `*`.

3. For each character in `S1`, update the `cur` array based on the rules derived from the DP recurrence.

4. After each row is processed, set `prev = cur` for the next iteration.

5. At the end, return the value of `prev[m]` where `m` is the length of `S2`.

### Time and Space Complexity

- **Time Complexity**: `O(n * m)` where `n` is the length of `S1` and `m` is the length of `S2`.
- **Space Complexity**: `O(m)` as we are using two rows of size `m` for space optimization.

### Solution Code

The C implementation of the space-optimized dynamic programming solution is in the `program.c` file.

## Running the Code

1. Clone this repository.
2. Compile the C file using a C compiler like GCC:
```bash
gcc program.c -o program
```
3. Run the compiled program:
```bash
./program
```

---

0 comments on commit 9d85e11

Please sign in to comment.