Complete-Preparation

πŸŽ‰ One-stop destination for all your technical interview Preparation πŸŽ‰

View the Project on GitHub

Wildcard Matching 🌟🌟🌟

Recursive Approach

Code

bool f(string& pattern, string& text, int i, int j)
{
    if (i < 0 && j < 0) return true;
    if (i < 0 && j >= 0) return false;
    if (j < 0 && i >= 0) {
        for (int k = 0; k <= i; k++) {
            if (pattern[k] != '*')
                return false;
        }
        return true;
    }

    if (pattern[i] == text[j] || pattern[i] == '?')
        return f(pattern, text, i - 1, j - 1);
    if (pattern[i] == '*'){
        int takeEmptyAndMove = f(pattern, text, i - 1, j);
        int takeOneCharAndStay = f(pattern, text, i, j - 1);
        return (takeEmptyAndMove || takeOneCharAndStay);
    }

    return false;
}

bool wildcardMatching(string pattern, string text)
{
    int n = pattern.size(), m = text.size();
    return f(pattern, text, n - 1, m - 1);
}

Memoization

Code-1

bool f(string& pattern, string& text, int i, int j, vector<vector<int>>& dp)
{
    if (i < 0 && j < 0) return true;
    if (i < 0 && j >= 0) return false;
    if (j < 0 && i >= 0) {
        for (int k = 0; k <= i; k++) {
            if (pattern[k] != '*')
                return false;
        }
        return true;
    }

    if (dp[i][j] != -1) return dp[i][j];

    if (pattern[i] == text[j] || pattern[i] == '?')
        return dp[i][j] = f(pattern, text, i - 1, j - 1, dp);
    if (pattern[i] == '*') {
        int takeEmptyAndMove = f(pattern, text, i - 1, j, dp);
        int takeOneCharAndStay = f(pattern, text, i, j - 1, dp);
        return dp[i][j] = (takeEmptyAndMove || takeOneCharAndStay);
    }

    return dp[i][j] = false;
}

bool wildcardMatching(string pattern, string text)
{
    int n = pattern.size(), m = text.size();
    vector<vector<int>> dp(n, vector<int>(m, -1));
    return f(pattern, text, n - 1, m - 1, dp);
}

Code-2

bool f(string& pattern, string& text, int i, int j, vector<vector<int>>& dp)
{
    // One based indexing
    if (i == 0 && j == 0) return true;
    if (i == 0 && j > 0) return false; // remember j>=0 became j>0
    if (j == 0 && i > 0) {
        for (int k = 1; k <= i; k++) {
            if (pattern[k - 1] != '*')
                return false;
        }
        return true;

    }


    if (dp[i][j] != -1) return dp[i][j];

    if (pattern[i - 1] == text[j - 1] || pattern[i - 1] == '?')
        return dp[i][j] = f(pattern, text, i - 1, j - 1, dp);
    if (pattern[i - 1] == '*') {
        int takeEmptyAndMove = f(pattern, text, i - 1, j, dp);
        int takeOneCharAndStay = f(pattern, text, i, j - 1, dp);
        return dp[i][j] = (takeEmptyAndMove || takeOneCharAndStay);
    }
    return dp[i][j] = false;
}

bool wildcardMatching(string pattern, string text)
{
    int n = pattern.size(), m = text.size();
    vector<vector<int>> dp(n + 1, vector<int>(m + 1, -1));
    return f(pattern, text, n, m, dp);
}

Tabulation(Bottom-Up)

Code

bool wildcardMatching(string pattern, string text)
{
    int n = pattern.size(), m = text.size();
    vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));
    dp[0][0] = true;

    // Don't need to do below loop as dp is initialized with false
    // Its just for understanding
    for (int j = 1; j <= m; j++) dp[0][j] = false;

    for (int i = 1; i <= n; i++) {
        bool flag = true;
        for (int k = 1; k <= i; k++) {
            if (pattern[k - 1] != '*') {
                flag = false;
                break;
            }
        }
        dp[i][0] = flag;
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (pattern[i - 1] == text[j - 1] || pattern[i - 1] == '?') {
                dp[i][j] = dp[i - 1][j - 1];
            } else if (pattern[i - 1] == '*') {
                int takeEmptyAndMove = dp[i - 1][j];
                int takeOneCharAndStay = dp[i][j - 1];
                dp[i][j] = (takeEmptyAndMove || takeOneCharAndStay);
            } else {
                dp[i][j] = false;
            }
        }
    }
    return dp[n][m];
}

Space optimized tabulation

Code

bool wildcardMatching(string pattern, string text)
{
    int n = pattern.size(), m = text.size();
    vector<bool> prev(m + 1, false), curr(m + 1, false);
    prev[0] = true;

    for (int i = 1; i <= n; i++) {
        bool flag = true;
        for (int k = 1; k <= i; k++) {
            if (pattern[k - 1] != '*') {
                flag = false;
                break;
            }
        }
        curr[0] = flag;
        for (int j = 1; j <= m; j++) {
            if (pattern[i - 1] == text[j - 1] || pattern[i - 1] == '?') {
                curr[j] = prev[j - 1];
            } else if (pattern[i - 1] == '*') {
                curr[j] = (prev[j] || curr[j - 1]);
            } else {
                curr[j] = false;
            }
        }
        prev = curr;
    }
    return prev[m];
}