Open In App

Wildcard Pattern Matching

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a text and a wildcard pattern, implement wildcard pattern matching algorithm that finds if wildcard pattern is matched with text. The matching should cover the entire text (not partial text). The wildcard pattern can include the characters ‘?’ and ‘*’ 

  • ‘?’ – matches any single character 
  • ‘*’ – Matches any sequence of characters (including the empty sequence)

For example:

Text = "baaabab",
Pattern = “*****ba*****ab", output : true
Pattern = "baaa?ab", output : true
Pattern = "ba*a?", output : true
Pattern = "a*ab", output : false

wildcard-pattern-matching

Each occurrence of ‘?’ character in wildcard pattern can be replaced with any other character and each occurrence of ‘*’ with a sequence of characters such that the wildcard pattern becomes identical to the input string after replacement.

Let’s consider any character in the pattern.

Case 1: The character is ‘*’ . Here two cases arises as follows:  

  1. We can ignore ‘*’ character and move to next character in the Pattern.
  2. ‘*’ character matches with one or more characters in Text. Here we will move to next character in the string.

Case 2: The character is ‘?’ 
We can ignore current character in Text and move to next character in the Pattern and Text.

Case 3: The character is not a wildcard character 
If current character in Text matches with current character in Pattern, we move to next character in the Pattern and Text. If they do not match, wildcard pattern and Text do not match.
We can use Dynamic Programming to solve this problem:

Let T[i][j] is true if first i characters in given string matches the first j characters of pattern. 

Recommended Practice

Method 1:Using Backtracking(Brute Force)

Firstly we should be going thorugh the backtracking method:

The implementation of the code:

C++




#include <iostream>
using namespace std;
 
bool isMatch(string s, string p) {
        //dry run this sample case on paper , if unable to understand what soln does
        // p = "a*bc" s = "abcbc"
        int sIdx = 0, pIdx = 0, lastWildcardIdx = -1, sBacktrackIdx = -1, nextToWildcardIdx = -1;
        while (sIdx < s.size()) {
            if (pIdx < p.size() && (p[pIdx] == '?' || p[pIdx] == s[sIdx])) {
                // chars match
                ++sIdx;
                ++pIdx;
            } else if (pIdx < p.size() && p[pIdx] == '*') {
                // wildcard, so chars match - store index.
                lastWildcardIdx = pIdx;
                nextToWildcardIdx = ++pIdx;
                sBacktrackIdx = sIdx;
                 
                //storing the pidx+1 as from there I want to match the remaining pattern
            } else if (lastWildcardIdx == -1) {
                // no match, and no wildcard has been found.
                return false;
            } else {
                // backtrack - no match, but a previous wildcard was found.
                pIdx = nextToWildcardIdx;
                sIdx = ++sBacktrackIdx;
                //backtrack string from previousbacktrackidx + 1 index to see if then new pidx and sidx have same chars, if that is the case that means wildcard can absorb the chars in b/w and still further we can run the algo, if at later stage it fails we can backtrack
            }
        }
        for(int i = pIdx; i < p.size(); i++){
            if(p[i] != '*') return false;
        }
        return true;
        // true if every remaining char in p is wildcard
    }
 
int main() {
 
    string str = "baaabab";
    string pattern = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
 
    if (isMatch(str, pattern))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}


Java




class Main {
    public static boolean isMatch(String s, String p) {
         //dry run this sample case on paper , if unable to understand what soln does
        // p = "a*bc" s = "abcbc"
      int sIdx = 0, pIdx = 0, lastWildcardIdx = -1, sBacktrackIdx = -1, nextToWildcardIdx = -1;
        while (sIdx < s.length()) {
            if (pIdx < p.length() && (p.charAt(pIdx) == '?' || p.charAt(pIdx) == s.charAt(sIdx))) {
                               // chars match
 
              ++sIdx;
                ++pIdx;
            } else if (pIdx < p.length() && p.charAt(pIdx) == '*') {
                                // wildcard, so chars match - store index.
 
              lastWildcardIdx = pIdx;
                nextToWildcardIdx = ++pIdx;
                sBacktrackIdx = sIdx;
                            //storing the pidx+1 as from there I want to match the remaining pattern
 
            } else if (lastWildcardIdx == -1) {
                               // no match, and no wildcard has been found.
 
              return false;
            } else {
                               // backtrack - no match, but a previous wildcard was found.
 
              pIdx = nextToWildcardIdx;
                sIdx = ++sBacktrackIdx;
             //backtrack string from previousbacktrackidx + 1 index to see if then new pidx and sidx have same chars, if that is the case that means wildcard can absorb the chars in b/w and still further we can run the algo, if at later stage it fails we can backtrack
            }
        }
        for(int i = pIdx; i < p.length(); i++) {
            if(p.charAt(i) != '*') {
                return false;
            }
        }
        return true;
              // true if every remaining char in p is wildcard
 
    }
 
    public static void main(String[] args) {
        String str = "baaabab";
        String pattern = "*****ba*****ab";
 
        if (isMatch(str, pattern)) {
            System.out.println("Yes");
        } else {
            System.out.println("No");
        }
    }
}


Python




def isMatch(s, p):
    m, n = len(s), len(p)
 
    # Create a 2D DP table to store matching information
    dp = [[False] * (n + 1) for _ in range(m + 1)]
 
    # Empty pattern matches empty string
    dp[0][0] = True
 
    # Fill the first row of the DP table (when s is empty)
    for j in range(1, n + 1):
        if p[j - 1] == '*':
            dp[0][j] = dp[0][j - 1]
 
    # Fill the DP table using bottom-up dynamic programming
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if p[j - 1] == '*':
                dp[i][j] = dp[i - 1][j] or dp[i][j - 1]
            elif p[j - 1] == '?' or p[j - 1] == s[i - 1]:
                dp[i][j] = dp[i - 1][j - 1]
 
    return dp[m][n]
 
str = "baaabab"
pattern = "*****ba*****ab"
 
if isMatch(str, pattern):
    print("Yes")
else:
    print("No")


C#




using System;
 
class Program {
    static bool IsMatch(string s, string p) {
        int sIdx = 0, pIdx = 0, lastWildcardIdx = -1, sBacktrackIdx = -1, nextToWildcardIdx = -1;
        while (sIdx < s.Length) {
            if (pIdx < p.Length && (p[pIdx] == '?' || p[pIdx] == s[sIdx])) {
                ++sIdx;
                ++pIdx;
            } else if (pIdx < p.Length && p[pIdx] == '*') {
                lastWildcardIdx = pIdx;
                nextToWildcardIdx = ++pIdx;
                sBacktrackIdx = sIdx;
            } else if (lastWildcardIdx == -1) {
                return false;
            } else {
                pIdx = nextToWildcardIdx;
                sIdx = ++sBacktrackIdx;
            }
        }
        for(int i = pIdx; i < p.Length; i++){
            if(p[i] != '*') return false;
        }
        return true;
    }
 
    static void Main() {
        string str = "baaabab";
        string pattern = "*****ba*****ab";
 
        if (IsMatch(str, pattern))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}


Javascript




function isMatch(s, p) {
    let sIdx = 0, pIdx = 0, lastWildcardIdx = -1, sBacktrackIdx = -1, nextToWildcardIdx = -1;
     
    while (sIdx < s.length) {
        if (pIdx < p.length && (p[pIdx] === '?' || p[pIdx] === s[sIdx])) {
            // Characters match
            sIdx++;
            pIdx++;
        } else if (pIdx < p.length && p[pIdx] === '*') {
            // Wildcard, so characters match - store the index.
            lastWildcardIdx = pIdx;
            nextToWildcardIdx = ++pIdx;
            sBacktrackIdx = sIdx;
        } else if (lastWildcardIdx === -1) {
            // No match, and no wildcard has been found.
            return false;
        } else {
            // Backtrack - no match, but a previous wildcard was found.
            pIdx = nextToWildcardIdx;
            sIdx = ++sBacktrackIdx;
        }
    }
     
    // Check if there are only wildcards left in the pattern.
    for (let i = pIdx; i < p.length; i++) {
        if (p[i] !== '*') return false;
    }
     
    return true;
}
 
// Driver code
const str = "baaabab";
const pattern = "*****ba*****ab";
 
if (isMatch(str, pattern))
    console.log("Yes");
else
    console.log("No");


Output

Yes




Time complexity: O(m x n)
Auxiliary space: O(m x n)

DP Initialization: 

// both text and pattern are null
T[0][0] = true;
// pattern is null
T[i][0] = false;
// text is null
T[0][j] = T[0][j - 1] if pattern[j – 1] is '*'

DP relation: 

// If current characters match, result is same as 
// result for lengths minus one. Characters match
// in two cases:
// a) If pattern character is '?' then it matches
// with any character of text.
// b) If current characters in both match
if ( pattern[j – 1] == ‘?’) ||
(pattern[j – 1] == text[i - 1])
T[i][j] = T[i-1][j-1]

// If we encounter ‘*’, two choices are possible-
// a) We ignore ‘*’ character and move to next
// character in the pattern, i.e., ‘*’
// indicates an empty sequence.
// b) '*' character matches with ith character in
// input
else if (pattern[j – 1] == ‘*’)
T[i][j] = T[i][j-1] || T[i-1][j]
else // if (pattern[j – 1] != text[i - 1])
T[i][j] = false

Implementation:

Below is the implementation of the above dynamic programming approach.

C++




// C++ program to implement wildcard
// pattern matching algorithm
#include <bits/stdc++.h>
using namespace std;
 
// Function that matches input str with
// given wildcard pattern
bool strmatch(char str[], char pattern[], int n, int m)
{
    // empty pattern can only match with
    // empty string
    if (m == 0)
        return (n == 0);
 
    // lookup table for storing results of
    // subproblems
    bool lookup[n + 1][m + 1];
 
    // initialize lookup table to false
    memset(lookup, false, sizeof(lookup));
 
    // empty pattern can match with empty string
    lookup[0][0] = true;
 
    // Only '*' can match with empty string
    for (int j = 1; j <= m; j++)
        if (pattern[j - 1] == '*')
            lookup[0][j] = lookup[0][j - 1];
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // Two cases if we see a '*'
            // a) We ignore ‘*’ character and move
            //    to next  character in the pattern,
            //     i.e., ‘*’ indicates an empty sequence.
            // b) '*' character matches with ith
            //     character in input
            if (pattern[j - 1] == '*')
                lookup[i][j]
                    = lookup[i][j - 1] || lookup[i - 1][j];
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            // (b) characters actually match
            else if (pattern[j - 1] == '?'
                     || str[i - 1] == pattern[j - 1])
                lookup[i][j] = lookup[i - 1][j - 1];
 
            // If characters don't match
            else
                lookup[i][j] = false;
        }
    }
 
    return lookup[n][m];
}
 
int main()
{
    char str[] = "baaabab";
    char pattern[] = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
 
    if (strmatch(str, pattern, strlen(str),
                 strlen(pattern)))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
 
    return 0;
}


Java




// Java program to implement wildcard
// pattern matching algorithm
import java.util.Arrays;
public class GFG {
 
    // Function that matches input str with
    // given wildcard pattern
    static boolean strmatch(String str, String pattern,
                            int n, int m)
    {
        // empty pattern can only match with
        // empty string
        if (m == 0)
            return (n == 0);
 
        // lookup table for storing results of
        // subproblems
        boolean[][] lookup = new boolean[n + 1][m + 1];
 
        // initialize lookup table to false
        for (int i = 0; i < n + 1; i++)
            Arrays.fill(lookup[i], false);
 
        // empty pattern can match with empty string
        lookup[0][0] = true;
 
        // Only '*' can match with empty string
        for (int j = 1; j <= m; j++)
            if (pattern.charAt(j - 1) == '*')
                lookup[0][j] = lookup[0][j - 1];
 
        // fill the table in bottom-up fashion
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                // Two cases if we see a '*'
                // a) We ignore '*'' character and move
                //    to next  character in the pattern,
                //     i.e., '*' indicates an empty
                //     sequence.
                // b) '*' character matches with ith
                //     character in input
                if (pattern.charAt(j - 1) == '*')
                    lookup[i][j] = lookup[i][j - 1]
                                   || lookup[i - 1][j];
 
                // Current characters are considered as
                // matching in two cases
                // (a) current character of pattern is '?'
                // (b) characters actually match
                else if (pattern.charAt(j - 1) == '?'
                         || str.charAt(i - 1)
                                == pattern.charAt(j - 1))
                    lookup[i][j] = lookup[i - 1][j - 1];
 
                // If characters don't match
                else
                    lookup[i][j] = false;
            }
        }
 
        return lookup[n][m];
    }
 
   
    // Driver code
    public static void main(String args[])
    {
        String str = "baaabab";
        String pattern = "*****ba*****ab";
        // String pattern = "ba*****ab";
        // String pattern = "ba*ab";
        // String pattern = "a*ab";
        // String pattern = "a*****ab";
        // String pattern = "*a*****ab";
        // String pattern = "ba*ab****";
        // String pattern = "****";
        // String pattern = "*";
        // String pattern = "aa?ab";
        // String pattern = "b*b";
        // String pattern = "a*a";
        // String pattern = "baaabab";
        // String pattern = "?baaabab";
        // String pattern = "*baaaba*";
 
        if (strmatch(str, pattern, str.length(),
                     pattern.length()))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
// This code is contributed by Sumit Ghosh


Python3




# Python program to implement wildcard
# pattern matching algorithm
 
# Function that matches input strr with
# given wildcard pattern
 
 
def strrmatch(strr, pattern, n, m):
 
    # empty pattern can only match with
    # empty string
    if (m == 0):
        return (n == 0)
 
    # lookup table for storing results of
    # subproblems
    lookup = [[False for i in range(m + 1)] for j in range(n + 1)]
 
    # empty pattern can match with empty string
    lookup[0][0] = True
 
    # Only '*' can match with empty string
    for j in range(1, m + 1):
        if (pattern[j - 1] == '*'):
            lookup[0][j] = lookup[0][j - 1]
 
    # fill the table in bottom-up fashion
    for i in range(1, n + 1):
        for j in range(1, m + 1):
 
            # Two cases if we see a '*'
            # a) We ignore ‘*’ character and move
            # to next character in the pattern,
            # i.e., ‘*’ indicates an empty sequence.
            # b) '*' character matches with ith
            # character in input
            if (pattern[j - 1] == '*'):
                lookup[i][j] = lookup[i][j - 1] or lookup[i - 1][j]
 
            # Current characters are considered as
            # matching in two cases
            # (a) current character of pattern is '?'
            # (b) characters actually match
            else if (pattern[j - 1] == '?' or strr[i - 1] == pattern[j - 1]):
                lookup[i][j] = lookup[i - 1][j - 1]
 
            # If characters don't match
            else:
                lookup[i][j] = False
 
    return lookup[n][m]
 
# Driver code
 
 
strr = "baaabab"
pattern = "*****ba*****ab"
# char pattern[] = "ba*****ab"
# char pattern[] = "ba*ab"
# char pattern[] = "a*ab"
# char pattern[] = "a*****ab"
# char pattern[] = "*a*****ab"
# char pattern[] = "ba*ab****"
# char pattern[] = "****"
# char pattern[] = "*"
# char pattern[] = "aa?ab"
# char pattern[] = "b*b"
# char pattern[] = "a*a"
# char pattern[] = "baaabab"
# char pattern[] = "?baaabab"
# char pattern[] = "*baaaba*"
 
if (strrmatch(strr, pattern, len(strr), len(pattern))):
    print("Yes")
else:
    print("No")
 
# This code is contributed by shubhamsingh10


C#




// C# program to implement wildcard
// pattern matching algorithm
using System;
 
class GFG {
 
    // Function that matches input str with
    // given wildcard pattern
    static Boolean strmatch(String str,
                            String pattern,
                            int n, int m)
    {
        // empty pattern can only match with
        // empty string
        if (m == 0)
            return (n == 0);
 
        // lookup table for storing results of
        // subproblems
        Boolean[, ] lookup = new Boolean[n + 1, m + 1];
 
        // initialize lookup table to false
        for (int i = 0; i < n + 1; i++)
            for (int j = 0; j < m + 1; j++)
                lookup[i, j] = false;
 
        // empty pattern can match with
        // empty string
        lookup[0, 0] = true;
 
        // Only '*' can match with empty string
        for (int j = 1; j <= m; j++)
            if (pattern[j - 1] == '*')
                lookup[0, j] = lookup[0, j - 1];
 
        // fill the table in bottom-up fashion
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                // Two cases if we see a '*'
                // a) We ignore '*'' character and move
                // to next character in the pattern,
                //     i.e., '*' indicates an empty
                //     sequence.
                // b) '*' character matches with ith
                //     character in input
                if (pattern[j - 1] == '*')
                    lookup[i, j] = lookup[i, j - 1]
                                   || lookup[i - 1, j];
 
                // Current characters are considered as
                // matching in two cases
                // (a) current character of pattern is '?'
                // (b) characters actually match
                else if (pattern[j - 1] == '?'
                         || str[i - 1] == pattern[j - 1])
                    lookup[i, j] = lookup[i - 1, j - 1];
 
                // If characters don't match
                else
                    lookup[i, j] = false;
            }
        }
        return lookup[n, m];
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        String str = "baaabab";
        String pattern = "*****ba*****ab";
        // String pattern = "ba*****ab";
        // String pattern = "ba*ab";
        // String pattern = "a*ab";
        // String pattern = "a*****ab";
        // String pattern = "*a*****ab";
        // String pattern = "ba*ab****";
        // String pattern = "****";
        // String pattern = "*";
        // String pattern = "aa?ab";
        // String pattern = "b*b";
        // String pattern = "a*a";
        // String pattern = "baaabab";
        // String pattern = "?baaabab";
        // String pattern = "*baaaba*";
 
        if (strmatch(str, pattern, str.Length,
                     pattern.Length))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
 
// JavaScript program to implement wildcard
// pattern matching algorithm
 
 
// Function that matches input str with
// given wildcard pattern
function strmatch(str, pattern, n, m)
{
    // empty pattern can only match with
    // empty string
    if (m == 0)
        return (n == 0);
 
    // lookup table for storing results of
    // subproblems
    // initialize lookup table to false
    let lookup = new Array(n + 1).fill(false).map(()=>new Array(m + 1).fill(false));
 
    // empty pattern can match with empty string
    lookup[0][0] = true;
 
    // Only '*' can match with empty string
    for (let j = 1; j <= m; j++)
        if (pattern[j - 1] == '*')
            lookup[0][j] = lookup[0][j - 1];
 
    // fill the table in bottom-up fashion
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            // Two cases if we see a '*'
            // a) We ignore ‘*’ character and move
            //    to next  character in the pattern,
            //     i.e., ‘*’ indicates an empty sequence.
            // b) '*' character matches with ith
            //     character in input
            if (pattern[j - 1] == '*')
                lookup[i][j]
                    = lookup[i][j - 1] || lookup[i - 1][j];
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            // (b) characters actually match
            else if (pattern[j - 1] == '?'
                     || str[i - 1] == pattern[j - 1])
                lookup[i][j] = lookup[i - 1][j - 1];
 
            // If characters don't match
            else
                lookup[i][j] = false;
        }
    }
 
    return lookup[n][m];
}
 
// driver code
 
let str = "baaabab";
let pattern = "*****ba*****ab";
// let pattern = "ba*****ab";
// let pattern = "ba*ab";
// let pattern = "a*ab";
// let pattern = "a*****ab";
// let pattern = "*a*****ab";
// let pattern = "ba*ab****";
// let pattern = "****";
// let pattern = "*";
// let pattern = "aa?ab";
// let pattern = "b*b";
// let pattern = "a*a";
// let pattern = "baaabab";
// let pattern = "?baaabab";
// let pattern = "*baaaba*";
 
if (strmatch(str, pattern, str.length,pattern.length))
    document.write("Yes","</br>")
else
    document.write("No","</br>")
   
// This code is contributed by shinjanpatra
 
</script>


Output

Yes




Time complexity: O(m x n) 
Auxiliary space: O(m x n)

Approach: DP Memoization solution

C++




// C++ program to implement wildcard
// pattern matching algorithm
 
#include <bits/stdc++.h>
 
using namespace std;
 
// Function that matches input str with
// given wildcard pattern
vector<vector<int> > dp;
int finding(string& s, string& p, int n, int m)
{
    // return 1 if n and m are negative
    if (n < 0 && m < 0)
        return 1;
 
    // return 0 if m is negative
    if (m < 0)
        return 0;
 
    // return n if n is negative
    if (n < 0) {
        // while m is positive
        while (m >= 0) {
            if (p[m] != '*')
                return 0;
            m--;
        }
        return 1;
    }
 
    // if dp state is not visited
    if (dp[n][m] == -1) {
        if (p[m] == '*') {
            return dp[n][m] = finding(s, p, n - 1, m)
                              || finding(s, p, n, m - 1);
        }
        else {
            if (p[m] != s[n] && p[m] != '?')
                return dp[n][m] = 0;
            else
                return dp[n][m]
                       = finding(s, p, n - 1, m - 1);
        }
    }
 
    // return dp[n][m] if dp state is previsited
    return dp[n][m];
}
 
bool isMatch(string s, string p)
{
    dp.clear();
 
    // resize the dp array
    dp.resize(s.size() + 1, vector<int>(p.size() + 1, -1));
    return dp[s.size()][p.size()]
           = finding(s, p, s.size() - 1, p.size() - 1);
}
 
// Driver code
int main()
{
    string str = "baaabab";
    string pattern = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
 
    if (isMatch(str, pattern))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
 
    return 0;
}


Java




//Java code for the above approach
import java.util.*;
 
class WildcardMatching {
    static int[][] dp;
  // Function that matches input str with
    // given wildcard pattern
    static boolean finding(String s, String p, int n, int m) {
        // return true if n and m are negative
        if (n < 0 && m < 0)
            return true;
 
        // return false if m is negative
        if (m < 0)
            return false;
 
        // return n if n is negative
        if (n < 0) {
            // while m is positive
            while (m >= 0) {
                if (p.charAt(m) != '*')
                    return false;
                m--;
            }
            return true;
        }
 
        // if dp state is not visited
        if (dp[n][m] == -1) {
            if (p.charAt(m) == '*') {
                dp[n][m] = (finding(s, p, n - 1, m) || finding(s, p, n, m - 1))?1:0;
                return (dp[n][m] == 1);
            } else {
                if (p.charAt(m) != s.charAt(n) && p.charAt(m) != '?') {
                    dp[n][m] = 0;
                    return false;
                } else {
                    dp[n][m] = (finding(s, p, n - 1, m - 1))?1:0;
                    return (dp[n][m] == 1);
                }
            }
        }
 
        // return dp[n][m] if dp state is previsited
        return (dp[n][m] == 1);
    }
    static boolean isMatch(String s, String p) {
        dp = new int[s.length() + 1][p.length() + 1];
        for (int i = 0; i < s.length() + 1; i++) {
            Arrays.fill(dp[i], -1);
        }
        return (finding(s, p, s.length() - 1, p.length() - 1) == true);
    }
//Driver code
    public static void main(String[] args) {
        String str = "baaabab";
        String pattern = "*****ba*****ab";
  // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
        if (isMatch(str, pattern)) {
            System.out.println("Yes");
        } else {
            System.out.println("No");
        }
    }
}


Python3




# Python program to implement wildcard
# pattern matching algorithm
def finding(s, p, n, m):
    # return 1 if n and m are negative
    if n < 0 and m < 0:
        return 1
 
    # return 0 if m is negative
    if m < 0:
        return 0
 
    # return n if n is negative
    if n < 0:
        # while m is positive
        while m >= 0:
            if p[m] != '*':
                return 0
            m -= 1
        return 1
 
    # if dp state is not visited
    if dp[n][m] == -1:
        if p[m] == '*':
            dp[n][m] = finding(s, p, n - 1, m) or finding(s, p, n, m - 1)
            return dp[n][m]
        else:
            if p[m] != s[n] and p[m] != '?':
                dp[n][m] = 0
                return dp[n][m]
            else:
                dp[n][m] = finding(s, p, n - 1, m - 1)
                return dp[n][m]
 
    # return dp[n][m] if dp state is previsited
    return dp[n][m]
 
def isMatch(s, p):
    global dp
    dp = []
 
    # resize the dp array
    for i in range(len(s) + 1):
        dp.append([-1] * (len(p) + 1))
    dp[len(s)][len(p)] = finding(s, p, len(s) - 1, len(p) - 1)
    return dp[len(s)][len(p)]
 
# Driver code
 
 
def main():
    s = "baaabab"
    p = "*****ba*****ab"
    # p = "ba*****ab"
    # p = "ba*ab"
    # p = "a*ab"
    # p = "a*****ab"
    # p = "*a*****ab"
    # p = "ba*ab****"
    # p = "****"
    # p = "*"
    # p = "aa?ab"
    # p = "b*b"
    # p = "a*a"
    # p = "baaabab"
    # p = "?baaabab"
    # p = "*baaaba*"
 
    if isMatch(s, p):
        print("Yes")
    else:
        print("No")
 
 
if __name__ == "__main__":
    main()
 
# This code is contributed by divyansh2212


C#




// C# program to implement wildcard
// pattern matching algorithm
using System;
using System.Collections.Generic;
 
class GFG
{
    // Function that matches input str with
    // given wildcard pattern
    static int finding(string s, string p, int n, int m, int[,]dp)
    {
        // return 1 if n and m are negative
        if (n < 0 && m < 0)
            return 1;
     
        // return 0 if m is negative
        if (m < 0)
            return 0;
     
        // return n if n is negative
        if (n < 0) {
            // while m is positive
            while (m >= 0) {
                if (p[m] != '*')
                    return 0;
                m--;
            }
            return 1;
        }
     
        // if dp state is not visited
        if (dp[n,m] == -1) {
            if (p[m] == '*')
            {
                if((finding(s, p, n - 1, m, dp)==1) || (finding(s, p, n, m - 1, dp)==1))
                {
                    dp[n,m]=1;
                    return dp[n,m];
                }
                 
            }
            else {
                if (p[m] != s[n] && p[m] != '?')
                    return dp[n,m] = 0;
                else
                    return dp[n,m]
                           = finding(s, p, n - 1, m - 1,dp);
            }
        }
     
        // return dp[n,m] if dp state is previsited
        return dp[n,m];
    }
     
    static int isMatch(string s, string p)
    {
        int [,]dp=new int[s.Length+1, p.Length+1];
     
        // resize the dp array
        for(int i=0; i<s.Length+1; i++)
        {
            for(int j=0; j<p.Length+1; j++)
                dp[i,j]=-1;
        }
        return dp[s.Length,p.Length] = finding(s, p, s.Length - 1, p.Length - 1,dp);
    }
     
    // Driver code
    public static void Main(String []args)
    {
        string str = "baaabab";
        string pattern = "*****ba*****ab";
        // char pattern[] = "ba*****ab";
        // char pattern[] = "ba*ab";
        // char pattern[] = "a*ab";
        // char pattern[] = "a*****ab";
        // char pattern[] = "*a*****ab";
        // char pattern[] = "ba*ab****";
        // char pattern[] = "****";
        // char pattern[] = "*";
        // char pattern[] = "aa?ab";
        // char pattern[] = "b*b";
        // char pattern[] = "a*a";
        // char pattern[] = "baaabab";
        // char pattern[] = "?baaabab";
        // char pattern[] = "*baaaba*";
     
        if (isMatch(str, pattern)==1)
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
     
    }
}


Javascript




<script>
 
// JavaScript program to implement wildcard
// pattern matching algorithm
 
// Function that matches input str with
// given wildcard pattern
let dp = [];
function finding(s, p, n, m)
{
    // return 1 if n and m are negative
    if (n < 0 && m < 0)
        return 1;
   
    // return 0 if m is negative
    if (m < 0)
        return 0;
   
    // return n if n is negative
    if (n < 0)
    {
        // while m is positive
        while (m >= 0)
        {
            if (p[m] != '*')
                return 0;
            m--;
        }
        return 1;
    }
    
    // if dp state is not visited
    if (dp[n][m] == -1)
    {
        if (p[m] == '*')
        {
            return dp[n][m] = finding(s, p, n - 1, m)
                              || finding(s, p, n, m - 1);
        }
        else
        {
            if (p[m] != s[n] && p[m] != '?')
                return dp[n][m] = 0;
            else
                return dp[n][m]
                       = finding(s, p, n - 1, m - 1);
        }
    }
   
    // return dp[n][m] if dp state is previsited
    return dp[n][m];
}
 
 
function isMatch(s, p)
{
    dp = [];
     
    // resize the dp array
    dp = new Array(s.length+1).fill(1).map(()=>new Array(p.length+1).fill(-1));
    return dp[s.length][p.length]
           = finding(s, p, s.length - 1, p.length - 1);
}
 
// Driver code
 
let str = "baaabab";
let pattern = "*****ba*****ab";
// char pattern[] = "ba*****ab";
// char pattern[] = "ba*ab";
// char pattern[] = "a*ab";
// char pattern[] = "a*****ab";
// char pattern[] = "*a*****ab";
// char pattern[] = "ba*ab****";
// char pattern[] = "****";
// char pattern[] = "*";
// char pattern[] = "aa?ab";
// char pattern[] = "b*b";
// char pattern[] = "a*a";
// char pattern[] = "baaabab";
// char pattern[] = "?baaabab";
// char pattern[] = "*baaaba*";
 
if (isMatch(str, pattern))
    console.log("Yes")
else
    console.log("No")
 
// This code is contributed by shinjanpatra
 
</script>


Output

Yes




Time complexity: O(m x n). 
Auxiliary space:  O(m x n). 

Further Scope: We can improve space complexity by making use of the fact that we only uses the result from last row. 

C++




// C++ program to implement wildcard
// pattern matching algorithm
#include <bits/stdc++.h>
using namespace std;
 
// Function that matches input str with
// given wildcard pattern
bool strmatch(char str[], char pattern[], int m, int n)
{
    // lookup table for storing results of
    // subproblems
    vector<bool> prev(m + 1, false), curr(m + 1, false);
 
    // empty pattern can match with empty string
    prev[0] = true;
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= n; i++) {
 
        bool flag = true;
        for (int ii = 1; ii < i; ii++) {
            if (pattern[ii - 1] != '*') {
                flag = false;
                break;
            }
        }
        curr[0] = flag; // for every row we are assigning
                        // 0th column value.
        for (int j = 1; j <= m; j++) {
            // Two cases if we see a '*'
            // a) We ignore ‘*’ character and move
            //    to next  character in the pattern,
            //     i.e., ‘*’ indicates an empty sequence.
            // b) '*' character matches with ith
            //     character in input
            if (pattern[i - 1] == '*')
                curr[j] = curr[j - 1] || prev[j];
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            // (b) characters actually match
            else if (pattern[i - 1] == '?'
                     || str[j - 1] == pattern[i - 1])
                curr[j] = prev[j - 1];
 
            // If characters don't match
            else
                curr[j] = false;
        }
        prev = curr;
    }
 
    return prev[m];
}
 
int main()
{
    char str[] = "baaabab";
    char pattern[] = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
 
    if (strmatch(str, pattern, strlen(str),
                 strlen(pattern)))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
 
    return 0;
}


Java




import java.util.Arrays;
 
class Main {
  // Function that matches input str with
  // given wildcard pattern
  public static boolean strmatch(String str, String pattern) {
    // lookup table for storing results of
    // subproblems
    boolean[] prev = new boolean[str.length() + 1];
    boolean[] curr = new boolean[str.length() + 1];
 
    // empty pattern can match with empty string
    prev[0] = true;
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= pattern.length(); i++) {
      boolean flag = true;
      for (int ii = 1; ii < i; ii++) {
        if (pattern.charAt(ii - 1) != '*') {
          flag = false;
          break;
        }
      }
      curr[0] = flag; // for every row we are assigning
      // 0th column value.
      for (int j = 1; j <= str.length(); j++) {
        // Two cases if we see a '*'
        // a) We ignore ‘*’ character and move
        //    to next character in the pattern,
        //     i.e., ‘*’ indicates an empty sequence.
        // b) '*' character matches with ith
        //     character in input
        if (pattern.charAt(i - 1) == '*')
          curr[j] = curr[j - 1] || prev[j];
 
        // Current characters are considered as
        // matching in two cases
        // (a) current character of pattern is '?'
        // (b) characters actually match
        else if (pattern.charAt(i - 1) == '?'
            || str.charAt(j - 1) == pattern.charAt(i - 1))
          curr[j] = prev[j - 1];
 
        // If characters don't match
        else
          curr[j] = false;
      }
      prev = Arrays.copyOf(curr, curr.length);
    }
 
    return prev[str.length()];
  }
 
  public static void main(String[] args) {
    String str = "baaabab";
    String pattern = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
     
    if (strmatch(str, pattern))
      System.out.println("Yes");
    else
      System.out.println("No");
  }
}
// This code is contributed by divyansh2212


Python3




# Python program to implement wildcard
# pattern matching algorithm
 
# Function that matches input str with
# given wildcard pattern
def strmatch(str, pattern, m, n):
    # lookup table for storing results of
    # subproblems
    prev, curr = [False]*(m+1), [False]*(m+1)
 
    # empty pattern can match with empty string
    prev[0] = True
 
    # fill the table in bottom-up fashion
    for i in range(1, n+1):
 
        flag = True
        for ii in range(1, i):
            if pattern[ii-1] != '*':
                flag = False
                break
        curr[0] = flag # for every row we are assigning
                        # 0th column value.
        for j in range(1, m+1):
            # Two cases if we see a '*'
            # a) We ignore '*' character and move
            #    to next  character in the pattern,
            #     i.e., '*' indicates an empty sequence.
            # b) '*' character matches with ith
            #     character in input
            if pattern[i-1] == '*':
                curr[j] = curr[j-1] or prev[j]
 
            # Current characters are considered as
            # matching in two cases
            # (a) current character of pattern is '?'
            # (b) characters actually match
            elif pattern[i-1] == '?' or str[j-1] == pattern[i-1]:
                curr[j] = prev[j-1]
 
            # If characters don't match
            else:
                curr[j] = False
        prev, curr = curr, prev
 
    return prev[m]
 
if __name__ == '__main__':
    str = "baaabab"
    pattern = "*****ba*****ab"
    # pattern = "ba*****ab"
    # pattern = "ba*ab"
    # pattern = "a*ab"
    # pattern = "a*****ab"
    # pattern = "*a*****ab"
    # pattern = "ba*ab****"
    # pattern = "****"
    # pattern = "*"
    # pattern = "aa?ab"
    # pattern = "b*b"
    # pattern = "a*a"
    # pattern = "baaabab"
    # pattern = "?baaabab"
    # pattern = "*baaaba*"
 
    if strmatch(str, pattern, len(str), len(pattern)):
        print("Yes")
    else:
        print("No")
 
 
# This code is contributed by rishabmalhdijo


C#




using System;
 
class Program
{
   
  // Function that matches input str with
  // given wildcard pattern
  public static bool StrMatch(string str, string pattern)
  {
     
    // lookup table for storing results of
    // subproblems
    bool[] prev = new bool[str.Length + 1];
    bool[] curr = new bool[str.Length + 1];
 
    // empty pattern can match with empty string
    prev[0] = true;
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= pattern.Length; i++) {
      bool flag = true;
      for (int ii = 1; ii < i; ii++) {
        if (pattern[ii - 1] != '*') {
          flag = false;
          break;
        }
      }
      curr[0] = flag; // for every row we are assigning
      // 0th column value.
      for (int j = 1; j <= str.Length; j++)
      {
         
        // Two cases if we see a '*'
        // a) We ignore ‘*’ character and move
        //    to next character in the pattern,
        //     i.e., ‘*’ indicates an empty sequence.
        // b) '*' character matches with ith
        //     character in input
        if (pattern[i - 1] == '*')
          curr[j] = curr[j - 1] || prev[j];
 
        // Current characters are considered as
        // matching in two cases
        // (a) current character of pattern is '?'
        // (b) characters actually match
        else if (pattern[i - 1] == '?'
            || str[j - 1] == pattern[i - 1])
          curr[j] = prev[j - 1];
 
        // If characters don't match
        else
          curr[j] = false;
      }
      prev = (bool[])curr.Clone();
    }
 
    return prev[str.Length];
  }
 
  public static void Main(string[] args) {
    string str = "baaabab";
    string pattern = "*****ba*****ab";
    // char pattern[] = "ba*****ab";
    // char pattern[] = "ba*ab";
    // char pattern[] = "a*ab";
    // char pattern[] = "a*****ab";
    // char pattern[] = "*a*****ab";
    // char pattern[] = "ba*ab****";
    // char pattern[] = "****";
    // char pattern[] = "*";
    // char pattern[] = "aa?ab";
    // char pattern[] = "b*b";
    // char pattern[] = "a*a";
    // char pattern[] = "baaabab";
    // char pattern[] = "?baaabab";
    // char pattern[] = "*baaaba*";
 
    if (StrMatch(str, pattern))
      Console.WriteLine("Yes");
    else
      Console.WriteLine("No");
  }
}


Javascript




// Function that matches input str with
// given wildcard pattern
function strmatch(str, pattern, m, n) {
 
    // lookup table for storing results of
    // subproblems
    let prev = new Array(m + 1).fill(false);
    let curr = new Array(m + 1).fill(false);
 
    // empty pattern can match with empty string
    prev[0] = true;
 
    // fill the table in bottom-up fashion
    for (let i = 1; i <= n; i++) {
 
        let flag = true;
        for (let ii = 1; ii < i; ii++) {
            if (pattern[ii - 1] != '*') {
                flag = false;
                break;
            }
        }
        curr[0] = flag; // for every row we are assigning
                        // 0th column value.
        for (let j = 1; j <= m; j++) {
            // Two cases if we see a '*'
            // a) We ignore ‘*’ character and move
            // to next character in the pattern,
            //     i.e., ‘*’ indicates an empty sequence.
            // b) '*' character matches with ith
            //     character in input
            if (pattern[i - 1] == '*')
                curr[j] = curr[j - 1] || prev[j];
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            // (b) characters actually match
            else if (pattern[i - 1] == '?'
                    || str[j - 1] == pattern[i - 1])
                curr[j] = prev[j - 1];
 
            // If characters don't match
            else
                curr[j] = false;
        }
        prev = curr.slice();
    }
 
    return prev[m];
}
 
let str = "baaabab";
let pattern = "*****ba*****ab";
// let pattern = "ba*****ab";
// let pattern = "ba*ab";
// let pattern = "a*ab";
// let pattern = "a*****ab";
// let pattern = "*a*****ab";
// let pattern = "ba*ab****";
// let pattern = "****";
// let pattern = "*";
// let pattern = "aa?ab";
// let pattern = "b*b";
// let pattern = "a*a";
// let pattern = "baaabab";
// let pattern = "?baaabab";
// let pattern = "*baaaba*";
 
if (strmatch(str, pattern, str.length, pattern.length))
    console.log("Yes");
else
    console.log("No");


Output

Yes




Time complexity: O(m x n).

Auxiliary space:  O(m). 

Approach: Greedy Method

We know in the greedy algorithm, we always find the temporary best solution and hope that it leads to a globally best or optimal solution.

At first, we initialize two pointers i and j to the beginning of the text and the pattern, respectively. We also initialize two variables startIndex and match to -1 and 0, respectively. startIndex will keep track of the position of the last ‘*’ character in the pattern, and match will keep track of the position in the text where the last proper match started.

We then loop through the text until we reach the end or find a character in the pattern that doesn’t match the corresponding character in the text. If the current characters match, we simply move to the next characters in both the pattern and the text. Ifnd if the pattern has a ‘?’ , we simply move to the next characters in both the pattern and the text. If the pattern has a ‘ ‘ character, then we mark the current position in the pattern and the text as a proper match by setting startIndex to the current position in the pattern and its match to the current position in the text. If there was no match and no ‘ ‘ character, then we understand we need to go through a different route henceforth, we backtrack to the last  ‘*’ character position and try a different match by setting j to startIndex + 1, match to match + 1, and i to match.

Once we have looped over the text, we consume any remaining ‘*’ characters in the pattern, and if we have reached the end of both the pattern and the text, the pattern matches the text.

Implementation:

Below is the implementation of the above greedy approach.

C++




#include <iostream>
using namespace std;
 
 
 
bool isMatch(string text, string pattern)
{
    int n = text.length();
    int m = pattern.length();
    int i = 0, j = 0, startIndex = -1, match = 0;
 
    while (i < n)
    {
        if (j < m && (pattern[j] == '?' || pattern[j] == text[i]))
        {
            // Characters match or '?' in pattern matches any character.
            i++;
            j++;
        }
        else if (j < m && pattern[j] == '*')
        {
            // Wildcard character '*', mark the current position in the pattern and the text as a proper match.
            startIndex = j;
            match = i;
            j++;
        }
        else if (startIndex != -1)
        {
            // No match, but a previous wildcard was found. Backtrack to the last '*' character position and try for a different match.
            j = startIndex + 1;
            match++;
            i = match;
        }
        else
        {
            // If none of the above cases comply, the pattern does not match.
            return false;
        }
    }
 
    // Consume any remaining '*' characters in the given pattern.
    while (j < m && pattern[j] == '*')
    {
        j++;
    }
 
    // If we have reached the end of both the pattern and the text, the pattern matches the text.
    return j == m;
}
 
int main()
{
    string str = "baaabab";
    string pattern = "*****ba*****ab";
 
    if (isMatch(str, pattern))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}


Java




import java.io.*;
 
class GFG {
    public static boolean isMatch(String text, String pattern)
    {
        int n = text.length();
        int m = pattern.length();
        int i = 0, j = 0, startIndex = -1, match = 0;
 
        while (i < n) {
            // If the current characters match or the
            // pattern has a '?', move to the next
            // characters in both pattern and text.
            if (j < m&& (pattern.charAt(j) == '?'|| pattern.charAt(j)== text.charAt(i))) {
                i++;
                j++;
            }
            // If the pattern has a '*' character, mark the
            // current position in the pattern and the text
            // as a proper match.
            else if (j < m && pattern.charAt(j) == '*') {
                startIndex = j;
                match = i;
                j++;
            }
            // If we have not found any match and no '*' character,
            // backtrack to the last '*' character position
            // and try for a different match.
            else if (startIndex != -1) {
                j = startIndex + 1;
                match++;
                i = match;
            }
            // If none of the above cases comply, the pattern
            // does not match.
            else {
                return false;
            }
        }
 
        // Consume any remaining '*' characters in the given
        // pattern.
        while (j < m && pattern.charAt(j) == '*') {
            j++;
        }
 
        // If we have reached the end of both the pattern
        // and the text, the pattern matches the text.
        return j == m;
    }
 
    public static void main(String[] args)
    {
        String str = "baaabab";
        String pattern = "*****ba*****ab";
        // char pattern[] = "ba*****ab";
        // char pattern[] = "ba*ab";
        // char pattern[] = "a*ab";
        // char pattern[] = "a*****ab";
        // char pattern[] = "*a*****ab";
        // char pattern[] = "ba*ab****";
        // char pattern[] = "****";
        // char pattern[] = "*";
        // char pattern[] = "aa?ab";
        // char pattern[] = "b*b";
        // char pattern[] = "a*a";
        // char pattern[] = "baaabab";
        // char pattern[] = "?baaabab";
        // char pattern[] = "*baaaba*";
 
        if (isMatch(str, pattern))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
// This code is contributed by Sovi


Python3




'''
This Python function checks whether a string 'text' matches a pattern 'pattern'
containing wildcard characters '?' and '*'.
'''
 
def isMatch(text, pattern):
    n = len(text)
    m = len(pattern)
    i = 0
    j = 0
    startIndex = -1
    match = 0
 
    while i < n:
        if j < m and (pattern[j] == '?' or pattern[j] == text[i]):
            # Characters match or '?' in pattern matches any character.
            i += 1
            j += 1
        elif j < m and pattern[j] == '*':
            # Wildcard character '*', mark the current position in the pattern and the text as a proper match.
            startIndex = j
            match = i
            j += 1
        elif startIndex != -1:
            # No match, but a previous wildcard was found. Backtrack to the last '*' character position and try for a different match.
            j = startIndex + 1
            match += 1
            i = match
        else:
            # If none of the above cases comply, the pattern does not match.
            return False
 
    # Consume any remaining '*' characters in the given pattern.
    while j < m and pattern[j] == '*':
        j += 1
 
    # If we have reached the end of both the pattern and the text, the pattern matches the text.
    return j == m
 
str = "baaabab"
pattern = "*****ba*****ab"
 
if isMatch(str, pattern):
    print("Yes")
else:
    print("No")


C#




using System;
 
class Solution {
    // Function to check if a string matches a pattern
    // containing '*' and '?'
    static bool IsMatch(string text, string pattern)
    {
        int n = text.Length;
        int m = pattern.Length;
        int i = 0, j = 0, startIndex = -1, match = 0;
 
        while (i < n) {
            if (j < m
                && (pattern[j] == '?'
                    || pattern[j] == text[i])) {
                // Characters match or '?' in pattern
                // matches any character.
                i++;
                j++;
            }
            else if (j < m && pattern[j] == '*') {
                // Wildcard character '*', mark the current
                // position in the pattern and the text as a
                // proper match.
                startIndex = j;
                match = i;
                j++;
            }
            else if (startIndex != -1) {
                // No match, but a previous wildcard was
                // found. Backtrack to the last '*'
                // character position and try for a
                // different match.
                j = startIndex + 1;
                match++;
                i = match;
            }
            else {
                // If none of the above cases comply, the
                // pattern does not match.
                return false;
            }
        }
 
        // Consume any remaining '*' characters in the given
        // pattern.
        while (j < m && pattern[j] == '*') {
            j++;
        }
 
        // If we have reached the end of both the pattern
        // and the text, the pattern matches the text.
        return j == m;
    }
 
    static void Main()
    {
        string str = "baaabab";
        string pattern = "*****ba*****ab";
 
        if (IsMatch(str, pattern))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}


Javascript




/*
* This JavaScript function checks whether a string 'text' matches a pattern 'pattern'
* containing wildcard characters '?' and '*'.
*/
 
function isMatch(text, pattern) {
    let n = text.length;
    let m = pattern.length;
    let i = 0, j = 0, startIndex = -1, match = 0;
 
    while (i < n) {
        if (j < m && (pattern[j] === '?' || pattern[j] === text[i])) {
            // Characters match or '?' in pattern matches any character.
            i++;
            j++;
        } else if (j < m && pattern[j] === '*') {
            // Wildcard character '*', mark the current position in the pattern and the text as a proper match.
            startIndex = j;
            match = i;
            j++;
        } else if (startIndex !== -1) {
            // No match, but a previous wildcard was found. Backtrack to the last '*' character position and try for a different match.
            j = startIndex + 1;
            match++;
            i = match;
        } else {
            // If none of the above cases comply, the pattern does not match.
            return false;
        }
    }
 
    // Consume any remaining '*' characters in the given pattern.
    while (j < m && pattern[j] === '*') {
        j++;
    }
 
    // If we have reached the end of both the pattern and the text, the pattern matches the text.
    return j === m;
}
 
const str = "baaabab";
const pattern = "*****ba*****ab";
 
if (isMatch(str, pattern))
    console.log("Yes");
else
    console.log("No");


Output

Yes




Time Complexity: O(n),  where n is the length of the given text.

Auxiliary Space: O(1),  because we only use constant amount of extra memory to store just the two pointers. 

One more improvement is you can merge consecutive ‘*’ in the pattern to single ‘*’ as they mean the same thing. For example for pattern “*****ba*****ab”, if we merge consecutive stars, the resultant string will be “*ba*ab”. So, value of m is reduced from 14 to 6.

This article is contributed by Aditya Goel.

 



Last Updated : 02 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads