Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
    • Practice Coding Problems
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • DSA
  • Interview Problems on DP
  • Practice DP
  • MCQs on DP
  • Tutorial on Dynamic Programming
  • Optimal Substructure
  • Overlapping Subproblem
  • Memoization
  • Tabulation
  • Tabulation vs Memoization
  • 0/1 Knapsack
  • Unbounded Knapsack
  • Subset Sum
  • LCS
  • LIS
  • Coin Change
  • Word Break
  • Egg Dropping Puzzle
  • Matrix Chain Multiplication
  • Palindrome Partitioning
  • DP on Arrays
  • DP with Bitmasking
  • Digit DP
  • DP on Trees
  • DP on Graph
Open In App
Next Article:
Wildcard Pattern Matching
Next article icon

Wildcard Pattern Matching

Last Updated : 20 Nov, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report
Try it on GfG Practice
redirect icon

Given a text txt and a wildcard pattern pat, implement a wildcard pattern matching algorithm that finds if the wildcard pattern is matched with the text. The matching should cover the entire text. The wildcard pattern can include the characters '?' and '*' which denote:

  • '?' - matches any single character 
  • '*' - Matches any sequence of characters (including the empty sequence)

Input: txt = "abcde", pat = "a?c*"
Output: true
Explanation: ? matches with b and * matches with "de".

Input: txt = "baaabab", pat = "a*ab"
Output: false
Explanation: Because in string pattern character 'a' at first position, pattern and text can't be matched.

Input: txt = "abc", pat = "*"
Output: true
Explanation: * matches with whole text "abc".

Table of Content

  • Using Recursion - O(2^(n+m)) Time and O(n) Space
  • Using Memoization - O(n*m) Time and O(n*m) Space
  • Using Bottom-Up DP (Tabulation) - O(n*m) Time and O(n*m) Space
  • Using Space Optimized DP - O(n*m) Time and O(m) Space
  • Simple Traversal Solution - O(n) Time and O(1) Space

Using Recursion - O(2^(n+m)) Time and O(n) Space

We start matching the last characters of the both pattern and text. There are three possible cases:

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

  1. We consider that '*' is equal to empty substring, and we move to the next character in pattern.
  2. We match '*' with one or more characters in Text. Here we move to next character in the text.

Case 2: The character is ‘?’ :
As '?' matches with any single character, we move to the next character in both pattern and text.

Case 3: The character in the pattern is not a wildcard: 
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, we return false.

C++
// C++ program for wildcard pattern matching using      // recursion  #include <iostream> #include <string> using namespace std;  bool wildCardRec(string& txt, string& pat, int n, int m) {          // Empty pattern can match with a empty text only     if (m == 0)         return (n == 0);      // Empty text can match with a pattern consisting      // of '*' only.     if (n == 0) {         for (int i = 0; i < m; i++)             if (pat[i] != '*')                 return false;         return true;     }      // Either the characters match or pattern has '?'     // move to the next in both text and pattern     if (txt[n - 1] == pat[m - 1] || pat[m - 1] == '?')         return wildCardRec(txt, pat, n - 1, m - 1);      // if the current character of pattern is '*'     // first case: It matches with zero character     // second case: It matches with one or more characters     if (pat[m - 1] == '*')         return wildCardRec(txt, pat, n, m - 1) ||                 wildCardRec(txt, pat, n - 1, m);          return false; }  bool wildCard(string txt, string pat) {     int n = txt.size();     int m = pat.size();     return wildCardRec(txt, pat, n, m); }  int main() {     string txt= "abcde";     string pat = "a*de";     cout << (wildCard(txt, pat) ? "true" : "false");      return 0; } 
Java
// Java program for wildcard pattern matching using recursion  class GfG {     static boolean wildCardRec(String txt,                           String pat, int n, int m) {                  // Empty pattern can match with an empty text only         if (m == 0)             return (n == 0);          // Empty text can match with a pattern consisting         // of '*' only.         if (n == 0) {             for (int i = 0; i < m; i++)                 if (pat.charAt(i) != '*')                     return false;             return true;         }          // Either the characters match or pattern has '?'         // move to the next in both text and pattern         if (txt.charAt(n - 1) == pat.charAt(m - 1) ||              					pat.charAt(m - 1) == '?')             return wildCardRec(txt, pat, n - 1, m - 1);          // if the current character of pattern is '*'         // first case: It matches with zero character         // second case: It matches with one or more characters         if (pat.charAt(m - 1) == '*')             return wildCardRec(txt, pat, n, m - 1) ||                     wildCardRec(txt, pat, n - 1, m);          return false;     }      static boolean wildCard(String txt, String pat) {         int n = txt.length();         int m = pat.length();         return wildCardRec(txt, pat, n, m);     }      public static void main(String[] args) {         String txt = "abcde";         String pat = "a*de";         System.out.println(wildCard(txt, pat) ? "true" : "false");     } } 
Python
# Python program for wildcard pattern matching using # recursion  def wildCardRec(txt, pat, n, m):          # Empty pattern can match with an empty text only     if m == 0:         return n == 0      # Empty text can match with a pattern consisting     # of '*' only.     if n == 0:         for i in range(m):             if pat[i] != '*':                 return False         return True      # Either the characters match or pattern has '?'     # move to the next in both text and pattern     if txt[n - 1] == pat[m - 1] or pat[m - 1] == '?':         return wildCardRec(txt, pat, n - 1, m - 1)      # if the current character of pattern is '*'     # first case: It matches with zero character     # second case: It matches with one or more characters     if pat[m - 1] == '*':         return wildCardRec(txt, pat, n, m - 1) or \                wildCardRec(txt, pat, n - 1, m)      return False  def wildCard(txt, pat):     n = len(txt)     m = len(pat)     return wildCardRec(txt, pat, n, m)  if __name__ == "__main__":     txt = "abcde"     pat = "a*de"     print("true" if wildCard(txt, pat) else "false") 
C#
// C# program for wildcard pattern  // matching using recursion  using System;  class GfG {     static bool wildCardRec(string txt,                              string pat, int n, int m) {                  // Empty pattern can match with an empty text only         if (m == 0)             return (n == 0);          // Empty text can match with a pattern consisting         // of '*' only.         if (n == 0) {             for (int i = 0; i < m; i++)                 if (pat[i] != '*')                     return false;             return true;         }          // Either the characters match or pattern has '?'         // move to the next in both text and pattern         if (txt[n - 1] == pat[m - 1] || pat[m - 1] == '?')             return wildCardRec(txt, pat, n - 1, m - 1);          // if the current character of pattern is '*'         // first case: It matches with zero character         // second case: It matches with one or more characters         if (pat[m - 1] == '*')             return wildCardRec(txt, pat, n, m - 1) ||                     wildCardRec(txt, pat, n - 1, m);          return false;     }      static bool wildCard(string txt, string pat) {         int n = txt.Length;         int m = pat.Length;         return wildCardRec(txt, pat, n, m);     }      static void Main(string[] args) {         string txt = "abcde";         string pat = "a*de";         Console.WriteLine(wildCard(txt, pat) ? "true" : "false");     } } 
JavaScript
// JavaScript program for wildcard pattern matching using // recursion  function wildCardRec(txt, pat, n, m) {      // Empty pattern can match with an empty text only     if (m === 0)         return (n === 0);      // Empty text can match with a pattern consisting     // of '*' only.     if (n === 0) {         for (let i = 0; i < m; i++)             if (pat[i] !== '*')                 return false;         return true;     }      // Either the characters match or pattern has '?'     // move to the next in both text and pattern     if (txt[n - 1] === pat[m - 1] || pat[m - 1] === '?')         return wildCardRec(txt, pat, n - 1, m - 1);      // if the current character of pattern is '*'     // first case: It matches with zero character     // second case: It matches with one or more characters     if (pat[m - 1] === '*')         return wildCardRec(txt, pat, n, m - 1) ||                 wildCardRec(txt, pat, n - 1, m);      return false; }  function wildCard(txt, pat) {     let n = txt.length;     let m = pat.length;     return wildCardRec(txt, pat, n, m); }  let txt = "abcde"; let pat = "a*de"; console.log(wildCard(txt, pat) ? "true" : "false"); 

Output
true

Using Memoization - O(n*m) Time and O(n*m) Space

In this problem, we can observe that the recursive solution holds the following two properties of Dynamic Programming:

1. Optimal Substructure: The result of matching a pattern pat of length m with a text txt of length n, i.e., wildCardRec(txt, pat, n, m), depends on the optimal solutions of its subproblems. If the current characters of pat and txt match (or if the character in pat is a '?'), then the solution depends on wildCardRec(txt, pat, n-1, m-1). If the current character in pat is an *, the solution of the problem will depend on the optimal result of wildCardRec(txt, pat, n, m-1) and wildCardRec(txt, pat, n-1, m).

2. Overlapping Subproblems: When using a recursive approach for the wildcard matching problem, we notice that certain subproblems are solved multiple times. For example, when solving wildCardRec(txt, pat, n, m), we may repeatedly compute results for subproblems like wildCardRec(txt, pat, n-1, m-1) or wildCardRec(txt, pat, n, m-1) in different recursive paths.

  • Since there are two parameters change in the recursive solution: the current indices of the text txt (ranging from 0 to n) and the pattern pat (ranging from 0 to m). Thus, we create a 2D array memo of size (n+1) by (m+1) for memoization.
  • We initialize this array with -1 to indicate that no subproblem has been computed initially.
  • We then modify our recursive solution to first check if memo[n][m] is -1; if it is, then only we proceed with further recursive calls.
C++
// C++ program for wildcard pattern  // matching using memoization     #include <iostream> #include <vector> #include <string> using namespace std;  bool wildCardRec(string& txt, string& pat,                      int n, int m, vector<vector<int>> &memo) {          // Empty pattern can match with a empty text only     if (m == 0)         return (n == 0);          // If result for this sub problem has been      // already computed, return it     if(memo[n][m] != -1)         return memo[n][m];              // Empty text can match with a pattern consisting      // of '*' only.     if (n == 0) {         for (int i = 0; i < m; i++)             if (pat[i] != '*')                 return memo[n][m] = false;         return memo[n][m] = true;     }      // Either the characters match or pattern has '?'     // move to the next in both text and pattern     if (txt[n - 1] == pat[m - 1] || pat[m - 1] == '?')         return memo[n][m] =                      wildCardRec(txt, pat, n - 1, m - 1, memo);      // if the current character of pattern is '*'     // first case: It matches with zero character     // second case: It matches with one or more characters     if (pat[m - 1] == '*')         return memo[n][m] =                          wildCardRec(txt, pat, n, m - 1, memo) ||                          wildCardRec(txt, pat, n - 1, m, memo);          return memo[n][m] = false; }  bool wildCard(string txt, string pat) {     int n = txt.size();     int m = pat.size();          vector<vector<int>> memo(n+1, vector<int>(m+1, -1));     return wildCardRec(txt, pat, n, m, memo); }  int main() {     string txt= "abcde";     string pat = "a*de";     cout << (wildCard(txt, pat) ? "true" : "false");      return 0; } 
Java
// Java program for wildcard pattern matching  // using memoization  import java.util.Arrays;  class GfG {     static boolean wildCardRec(String txt,                         String pat, int n, int m, int[][] memo) {                  // Empty pattern can match with an empty text only         if (m == 0)             return (n == 0);                  // If result for this subproblem has been        	// already computed, return it         if (memo[n][m] != -1)             return memo[n][m] == 1;                  // Empty text can match with a          // pattern consisting of '*' only.         if (n == 0) {             for (int i = 0; i < m; i++) {                 if (pat.charAt(i) != '*') {                     memo[n][m] = 0;                   	return false;                 }             }             memo[n][m] = 1;           	return true;         }          // Either the characters match or pattern has '?'         // Move to the next in both text and pattern         if (txt.charAt(n - 1) == pat.charAt(m - 1) || pat.charAt(m - 1) == '?') {             memo[n][m] = wildCardRec(txt, pat, n - 1, m - 1, memo) ? 1 : 0;             return memo[n][m] == 1;         }                  // If the current character of pattern is '*'         // First case: It matches with zero character         // Second case: It matches with one or more characters         if (pat.charAt(m - 1) == '*') {             memo[n][m] = (wildCardRec(txt, pat, n, m - 1, memo)                          || wildCardRec(txt, pat, n - 1, m, memo)) ? 1 : 0;             return memo[n][m] == 1;         }          memo[n][m] = 0;        	return false;     }      static boolean wildCard(String txt, String pat) {         int n = txt.length();         int m = pat.length();         int[][] memo = new int[n + 1][m + 1];         for (int[] row : memo)             Arrays.fill(row, -1);         return wildCardRec(txt, pat, n, m, memo);     }      public static void main(String[] args) {         String txt = "abcde";         String pat = "a*de";         System.out.println(wildCard(txt, pat) ? "true" : "false");     } } 
Python
# Python program for wildcard pattern # matching using memoization  def wildCardRec(txt, pat, n, m, memo):          # Empty pattern can match with an empty text only     if m == 0:         return n == 0          # If result for this subproblem has been      # already computed, return it     if memo[n][m] != -1:         return memo[n][m]              # Empty text can match with a pattern consisting      # of '*' only.     if n == 0:         for i in range(m):             if pat[i] != '*':                 memo[n][m] = False                 return False         memo[n][m] = True         return True      # Either the characters match or pattern has '?'     # move to the next in both text and pattern     if txt[n - 1] == pat[m - 1] or pat[m - 1] == '?':         memo[n][m] = wildCardRec(txt, pat, n - 1, m - 1, memo)         return memo[n][m]      # if the current character of pattern is '*'     # first case: It matches with zero character     # second case: It matches with one or more characters     if pat[m - 1] == '*':         memo[n][m] = wildCardRec(txt, pat, n, m - 1, memo) \         or wildCardRec(txt, pat, n - 1, m, memo)         return memo[n][m]          memo[n][m] = False     return False  def wildCard(txt, pat):     n = len(txt)     m = len(pat)     memo = [[-1 for _ in range(m + 1)] for _ in range(n + 1)]     return wildCardRec(txt, pat, n, m, memo)  if __name__ == "__main__":     txt = "abcde"     pat = "a*de"     print("true" if wildCard(txt, pat) else "false") 
C#
// C# program for wildcard pattern matching // using memoization  using System;  class GfG {     static bool WildCardRec(string txt, string pat,                              	int n, int m, int[,] memo) {                // Empty pattern can match with an empty       	// text only         if (m == 0)             return (n == 0);          // If result for this subproblem has been        	// already computed, return it         if (memo[n, m] != -1)             return memo[n, m] == 1;          // Empty text can match with a pattern        	// consisting of '*' only.         if (n == 0) {             for (int i = 0; i < m; i++) {                 if (pat[i] != '*') {                     memo[n, m] = 0;                     return false;                 }             }             memo[n, m] = 1;             return true;         }          // Either the characters match or pattern has '?'         // Move to the next in both text and pattern         if (txt[n - 1] == pat[m - 1] || pat[m - 1] == '?') {             memo[n, m] = WildCardRec(txt, pat, n - 1, m - 1, memo) ? 1 : 0;             return memo[n, m] == 1;         }          // If the current character of pattern is '*'         // First case: It matches with zero character         // Second case: It matches with one or more characters         if (pat[m - 1] == '*') {             memo[n, m] = (WildCardRec(txt, pat, n, m - 1, memo)                            	|| WildCardRec(txt, pat, n - 1, m, memo)) ? 1 : 0;             return memo[n, m] == 1;         }          memo[n, m] = 0;         return false;     }      static bool WildCard(string txt, string pat) {         int n = txt.Length;         int m = pat.Length;         int[,] memo = new int[n + 1, m + 1];          // Initialize memo array with -1         for (int i = 0; i <= n; i++) {             for (int j = 0; j <= m; j++)                 memo[i, j] = -1;         }          return WildCardRec(txt, pat, n, m, memo);     }      static void Main(string[] args) {         string txt = "abcde";         string pat = "a*de";         Console.WriteLine(WildCard(txt, pat) ? "true" : "false");     } } 
JavaScript
// JavaScript program for wildcard pattern  // matching using memoization  function wildCardRec(txt, pat, n, m, memo) {          // Empty pattern can match with an empty text only     if (m === 0)         return n === 0;          // If result for this subproblem has been      // already computed, return it     if (memo[n][m] !== -1)         return memo[n][m];              // Empty text can match with a pattern consisting      // of '*' only.     if (n === 0) {         for (let i = 0; i < m; i++)             if (pat[i] !== '*')                 return memo[n][m] = false;         return memo[n][m] = true;     }      // Either the characters match or pattern has '?'     // move to the next in both text and pattern     if (txt[n - 1] === pat[m - 1] || pat[m - 1] === '?')         return memo[n][m] = wildCardRec(txt, pat, n - 1, m - 1, memo);      // if the current character of pattern is '*'     // first case: It matches with zero character     // second case: It matches with one or more characters     if (pat[m - 1] === '*')         return memo[n][m] = wildCardRec(txt, pat, n, m - 1, memo)          						|| wildCardRec(txt, pat, n - 1, m, memo);          return memo[n][m] = false; }  function wildCard(txt, pat) {     let n = txt.length;     let m = pat.length;     let memo = Array.from(Array(n + 1), () => Array(m + 1).fill(-1));     return wildCardRec(txt, pat, n, m, memo); }  const txt = "abcde"; const pat = "a*de"; console.log(wildCard(txt, pat) ? "true" : "false"); 

Output
true

Using Bottom-Up DP (Tabulation) - O(n*m) Time and O(n*m) Space

The approach is similar to the previous one; however, instead of solving the problem recursively, we iteratively build the solution using a bottom-up manner. We maintain a dp[][] table such that dp[i][j] stores whether the pattern pat[0...j-1] matches with the text txt[0...i-1].

C++
// C++ program for wild card matching  // using tabulation  #include <iostream> #include <string> #include <vector> using namespace std;  bool wildCard(string& txt, string& pat) {     int n = txt.size();     int m = pat.size();      // dp[i][j] will be true if txt[0..i-1] matches pat[0..j-1]     vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false));      // Empty pattern matches with empty string     dp[0][0] = true;      // Handle patterns with '*' at the beginning     for (int j = 1; j <= m; j++)         if (pat[j - 1] == '*')             dp[0][j] = dp[0][j - 1];      for (int i = 1; i <= n; i++) {         for (int j = 1; j <= m; j++) {             if (pat[j - 1] == txt[i - 1] || pat[j - 1] == '?') {                                  // Either the characters match or pattern has '?'                 // result will be same as previous state                 dp[i][j] = dp[i - 1][j - 1];             }                          else if (pat[j - 1] == '*') {                                // if the current character of pattern is '*'                 // first case: It matches with zero character                 // second case: It matches with one or more                  dp[i][j] = dp[i][j - 1] || dp[i - 1][j];             }         }     }      return dp[n][m]; }  int main() {     string txt = "abcde";     string pat = "a*de";     cout << (wildCard(txt, pat) ? "true" : "false") << endl;     return 0; } 
Java
// Java program for wild card matching using tabulation  import java.util.Arrays;  class GfG {     static boolean wildCard(String txt, String pat) {         int n = txt.length();         int m = pat.length();          // dp[i][j] will be true if txt[0..i-1] matches pat[0..j-1]         boolean[][] dp = new boolean[n + 1][m + 1];          // Empty pattern matches with empty string         dp[0][0] = true;          // Handle patterns with '*' at the beginning         for (int j = 1; j <= m; j++)             if (pat.charAt(j - 1) == '*')                 dp[0][j] = dp[0][j - 1];          for (int i = 1; i <= n; i++) {             for (int j = 1; j <= m; j++) {                 if (pat.charAt(j - 1) == txt.charAt(i - 1)                      			|| pat.charAt(j - 1) == '?') {                                          // Either the characters match or pattern has '?'                     // result will be same as previous state                     dp[i][j] = dp[i - 1][j - 1];                 }                                  else if (pat.charAt(j - 1) == '*') {                                        // if the current character of pattern is '*'                     // first case: It matches with zero character                     // second case: It matches with one or more                      dp[i][j] = dp[i][j - 1] || dp[i - 1][j];                 }             }         }          return dp[n][m];     }      public static void main(String[] args) {         String txt = "abcde";         String pat = "a*de";         System.out.println(wildCard(txt, pat) ? "true" : "false");     } } 
Python
# Python program for wild card matching using tabulation  def wildCard(txt, pat):     n = len(txt)     m = len(pat)          # dp[i][j] will be True if txt[0..i-1] matches pat[0..j-1]     dp = [[False] * (m + 1) for _ in range(n + 1)]      # Empty pattern matches with empty string     dp[0][0] = True      # Handle patterns with '*' at the beginning     for j in range(1, m + 1):         if pat[j - 1] == '*':             dp[0][j] = dp[0][j - 1]      for i in range(1, n + 1):         for j in range(1, m + 1):             if pat[j - 1] == txt[i - 1] or pat[j - 1] == '?':                                  # Either the characters match or pattern has '?'                 # result will be same as previous state                 dp[i][j] = dp[i - 1][j - 1]                              elif pat[j - 1] == '*':                                  # if the current character of pattern is '*'                 # first case: It matches with zero character                 # second case: It matches with one or more                 dp[i][j] = dp[i][j - 1] or dp[i - 1][j]      return dp[n][m]  if __name__ == "__main__":     txt = "abcde"     pat = "a*de"     print("true" if wildCard(txt, pat) else "false") 
C#
// C# program for wild card matching using tabulation  using System;  class GfG {     static bool WildCard(string txt, string pat) {         int n = txt.Length;         int m = pat.Length;          // dp[i, j] will be true if txt[0..i-1] matches pat[0..j-1]         bool[,] dp = new bool[n + 1, m + 1];          // Empty pattern matches with empty string         dp[0, 0] = true;          // Handle patterns with '*' at the beginning         for (int j = 1; j <= m; j++)             if (pat[j - 1] == '*')                 dp[0, j] = dp[0, j - 1];          for (int i = 1; i <= n; i++) {             for (int j = 1; j <= m; j++) {                 if (pat[j - 1] == txt[i - 1] || pat[j - 1] == '?') {                                          // Either the characters match or pattern has '?'                     // result will be same as previous state                     dp[i, j] = dp[i - 1, j - 1];                 }                                  else if (pat[j - 1] == '*') {                                        // if the current character of pattern is '*'                     // first case: It matches with zero character                     // second case: It matches with one or more                      dp[i, j] = dp[i, j - 1] || dp[i - 1, j];                 }             }         }          return dp[n, m];     }      static void Main(string[] args) {         string txt = "abcde";         string pat = "a*de";         Console.WriteLine(WildCard(txt, pat) ? "true" : "false");     } } 
JavaScript
// JavaScript program for wild card matching using tabulation  function wildCard(txt, pat) {     const n = txt.length;     const m = pat.length;      // dp[i][j] will be true if txt[0..i-1] matches pat[0..j-1]     const dp = Array.from({ length: n + 1 }, () => Array(m + 1).fill(false));      // Empty pattern matches with empty string     dp[0][0] = true;      // Handle patterns with '*' at the beginning     for (let j = 1; j <= m; j++)         if (pat[j - 1] === '*')             dp[0][j] = dp[0][j - 1];      for (let i = 1; i <= n; i++) {         for (let j = 1; j <= m; j++) {             if (pat[j - 1] === txt[i - 1] || pat[j - 1] === '?') {                                  // Either the characters match or pattern has '?'                 // result will be same as previous state                 dp[i][j] = dp[i - 1][j - 1];             }                           else if (pat[j - 1] === '*') {                                // if the current character of pattern is '*'                 // first case: It matches with zero character                 // second case: It matches with one or more                 dp[i][j] = dp[i][j - 1] || dp[i - 1][j];             }         }     }      return dp[n][m]; }  const txt = "abcde"; const pat = "a*de"; console.log(wildCard(txt, pat) ? "true" : "false"); 

Output
true 

Using Space Optimized DP - O(n*m) Time and O(m) Space

If we take a closer look at the above solution, we can notice that we use only row entries, previous and current one. Therefore we can optimize the space by storing only rows.

C++
// C++ program for wild card matching using  // space optimized dp  #include <iostream> #include <string> #include <vector> using namespace std;  bool wildCard(string txt, string pat) {     int n = txt.size();     int m = pat.size();      vector<bool> prev(m+1, false);     vector<bool> curr(m+1, false);      // Empty pattern matches with empty string     prev[0] = true;      // Handle patterns with '*' at the beginning     for (int j = 1; j <= m; j++)         if (pat[j - 1] == '*')             prev[j] = prev[j-1];      for (int i = 1; i <= n; i++) {         for (int j = 1; j <= m; j++) {             if (pat[j - 1] == txt[i - 1] || pat[j - 1] == '?') {                                  // Either the characters match or pattern has '?'                 // result will be same as previous state                 curr[j] = prev[j - 1];             }                          else if (pat[j - 1] == '*') {                                // if the current character of pattern is '*'                 // first case: It matches with zero character                 // second case: It matches with one or more                  curr[j] = curr[j - 1] || prev[j];             }         }                  prev = curr;     }      return prev[m]; }  int main() {     string txt = "abcde";     string pat = "a*de";     cout << (wildCard(txt, pat) ? "true" : "false") << endl;     return 0; } 
Java
// Java program for wild card matching using space optimized  // dp  class GfG {     static boolean wildCard(String txt, String pat) {         int n = txt.length();         int m = pat.length();          boolean[] prev = new boolean[m + 1];         boolean[] curr = new boolean[m + 1];          // Empty pattern matches with empty string         prev[0] = true;          // Handle patterns with '*' at the beginning         for (int j = 1; j <= m; j++)             if (pat.charAt(j - 1) == '*')                 prev[j] = prev[j - 1];          for (int i = 1; i <= n; i++) {             for (int j = 1; j <= m; j++) {                 if (pat.charAt(j - 1) == txt.charAt(i - 1)                      				|| pat.charAt(j - 1) == '?') {                                          // Either the characters match or pattern has '?'                     // result will be same as previous state                     curr[j] = prev[j - 1];                 }                                   else if (pat.charAt(j - 1) == '*') {                                        // if the current character of pattern is '*'                     // first case: It matches with zero character                     // second case: It matches with one or more                      curr[j] = curr[j - 1] || prev[j];                 } else {                     curr[j] = false;                 }             }                          // Copy current row to previous row             System.arraycopy(curr, 0, prev, 0, m + 1);         }          return prev[m];     }      public static void main(String[] args) {         String txt = "abcde";         String pat = "a*de";         System.out.println(wildCard(txt, pat) ? "true" : "false");     } } 
Python
# Python program for wild card matching using space optimized  # DP  def wildCard(txt, pat):     n = len(txt)     m = len(pat)          prev = [False] * (m + 1)     curr = [False] * (m + 1)      # Empty pattern matches with empty string     prev[0] = True      # Handle patterns with '*' at the beginning     for j in range(1, m + 1):         if pat[j - 1] == '*':             prev[j] = prev[j - 1]      for i in range(1, n + 1):         for j in range(1, m + 1):             if pat[j - 1] == txt[i - 1] or pat[j - 1] == '?':                                  # Either the characters match or pattern has '?'                 # result will be same as previous state                 curr[j] = prev[j - 1]                          elif pat[j - 1] == '*':                                  # if the current character of pattern is '*'                 # first case: It matches with zero character                 # second case: It matches with one or more                 curr[j] = curr[j - 1] or prev[j]             else:                 curr[j] = False                  # Copy current row to previous row         prev = curr[:]      return prev[m]  txt = "abcde" pat = "a*de" print("true" if wildCard(txt, pat) else "false") 
C#
// C# program for wild card matching using Space optimized DP  using System;  class GfG {     static bool WildCard(string txt, string pat) {         int n = txt.Length;         int m = pat.Length;          bool[] prev = new bool[m + 1];         bool[] curr = new bool[m + 1];          // Empty pattern matches with empty string         prev[0] = true;          // Handle patterns with '*' at the beginning         for (int j = 1; j <= m; j++)             if (pat[j - 1] == '*')                 prev[j] = prev[j - 1];          for (int i = 1; i <= n; i++) {             for (int j = 1; j <= m; j++) {                 if (pat[j - 1] == txt[i - 1] || pat[j - 1] == '?') {                                          // Either the characters match or pattern has '?'                     // result will be same as previous state                     curr[j] = prev[j - 1];                 }                                   else if (pat[j - 1] == '*') {                                        // if the current character of pattern is '*'                     // first case: It matches with zero character                     // second case: It matches with one or more                      curr[j] = curr[j - 1] || prev[j];                 } else {                     curr[j] = false;                 }             }                          // Copy current row to previous row             Array.Copy(curr, prev, m + 1);         }          return prev[m];     }      static void Main(string[] args) {         string txt = "abcde";         string pat = "a*de";         Console.WriteLine(WildCard(txt, pat) ? "true" : "false");     } } 
JavaScript
// JavaScript program for wild card matching using space optimized // DP  function wildCard(txt, pat) {     const n = txt.length;     const m = pat.length;      let prev = new Array(m + 1).fill(false);     let curr = new Array(m + 1).fill(false);      // Empty pattern matches with empty string     prev[0] = true;      // Handle patterns with '*' at the beginning     for (let j = 1; j <= m; j++) {         if (pat[j - 1] === '*')             prev[j] = prev[j - 1];     }      for (let i = 1; i <= n; i++) {         for (let j = 1; j <= m; j++) {             if (pat[j - 1] === txt[i - 1] || pat[j - 1] === '?') {                                  // Either the characters match or pattern has '?'                 // result will be same as previous state                 curr[j] = prev[j - 1];             }                           else if (pat[j - 1] === '*') {                                // if the current character of pattern is '*'                 // first case: It matches with zero character                 // second case: It matches with one or more                  curr[j] = curr[j - 1] || prev[j];             } else {                 curr[j] = false;             }         }                  // Copy current row to previous row         prev = [...curr];     }      return prev[m]; }  const txt = "abcde"; const pat = "a*de"; console.log(wildCard(txt, pat) ? "true" : "false"); 

Output
true 

Simple Traversal Solution - O(n) Time and O(1) Space

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.

C++
// C++ program for wild card matching using single // traversal       #include <iostream> using namespace std;  bool wildCard(string txt, string pat) {     int n = txt.length();     int m = pat.length();     int i = 0, j = 0, startIndex = -1, match = 0;      while (i < n) {                  // Characters match or '?' in pattern matches         // any character.         if (j < m && (pat[j] == '?' || pat[j] == txt[i])) {                       i++;             j++;         }                  else if (j < m && pat[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 && pat[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 txt = "baaabab";     string pat = "*****ba*****ab";          cout << (wildCard(txt, pat) ? "true" : "false"); } 
Java
// Java program for wild card matching using single // traversal  class GfG {     static boolean wildCard(String txt, String pat) {         int n = txt.length();         int m = pat.length();         int i = 0, j = 0, startIndex = -1, match = 0;          while (i < n) {              // Characters match or '?' in pattern matches             // any character.             if (j < m && (pat.charAt(j) == '?'                            	|| pat.charAt(j) == txt.charAt(i))) {                 i++;                 j++;             }              else if (j < m && pat.charAt(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 && pat.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 txt = "baaabab";         String pat = "*****ba*****ab";          System.out.println(wildCard(txt, pat) ? "true" : "false");     } } 
Python
# Python program for wild card matching using single # traversal  def wildCard(txt, pat):     n = len(txt)     m = len(pat)     i = 0     j = 0     startIndex = -1     match = 0      while i < n:          # Characters match or '?' in pattern matches         # any character.         if j < m and (pat[j] == '?' or pat[j] == txt[i]):             i += 1             j += 1          elif j < m and pat[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 pat[j] == '*':         j += 1      # If we have reached the end of both the pattern and     # the text, the pattern matches the text.     return j == m   if __name__ == "__main__":     txt = "baaabab"     pat = "*****ba*****ab"     print("true" if wildCard(txt, pat) else "false") 
C#
// C# program for wild card matching using single // traversal  using System;  class GfG {     static bool WildCard(string txt, string pat) {         int n = txt.Length;         int m = pat.Length;         int i = 0, j = 0, startIndex = -1, match = 0;          while (i < n) {              // Characters match or '?' in pattern matches             // any character.             if (j < m && (pat[j] == '?' || pat[j] == txt[i])) {                 i++;                 j++;             }              else if (j < m && pat[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 && pat[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[] args) {         string txt = "baaabab";         string pat = "*****ba*****ab";          Console.WriteLine(WildCard(txt, pat) ? "true" : "false");     } } 
JavaScript
// JavaScript program for wild card matching using single // traversal  function wildCard(txt, pat) {     let n = txt.length;     let m = pat.length;     let i = 0, j = 0, startIndex = -1, match = 0;      while (i < n) {          // Characters match or '?' in pattern matches         // any character.         if (j < m && (pat[j] === '?' || pat[j] === txt[i])) {             i++;             j++;         }          else if (j < m && pat[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 && pat[j] === '*') {         j++;     }      // If we have reached the end of both the pattern and     // the text, the pattern matches the text.     return j === m; }  let txt = "baaabab"; let pat = "*****ba*****ab"; console.log(wildCard(txt, pat) ? "true" : "false"); 

Output
true

Next Article
Wildcard Pattern Matching

K

kartik
Improve
Article Tags :
  • Strings
  • Dynamic Programming
  • Pattern Searching
  • DSA
  • Microsoft
  • Amazon
  • Walmart
  • Zoho
  • InMobi
  • United Health Group
  • Ola Cabs
Practice Tags :
  • Amazon
  • InMobi
  • Microsoft
  • Ola Cabs
  • United Health Group
  • Walmart
  • Zoho
  • Dynamic Programming
  • Pattern Searching
  • Strings

Similar Reads

    What is Pattern Searching ?
    Pattern searching in Data Structures and Algorithms (DSA) is a fundamental concept that involves searching for a specific pattern or sequence of elements within a given data structure. This technique is commonly used in string matching algorithms to find occurrences of a particular pattern within a
    5 min read
    Introduction to Pattern Searching - Data Structure and Algorithm Tutorial
    Pattern searching is an algorithm that involves searching for patterns such as strings, words, images, etc. We use certain algorithms to do the search process. The complexity of pattern searching varies from algorithm to algorithm. They are very useful when performing a search in a database. The Pat
    15+ min read
    Naive algorithm for Pattern Searching
    Given text string with length n and a pattern with length m, the task is to prints all occurrences of pattern in text. Note: You may assume that n > m. Examples:  Input:  text = "THIS IS A TEST TEXT", pattern = "TEST"Output: Pattern found at index 10 Input:  text =  "AABAACAADAABAABA", pattern =
    6 min read
    Rabin-Karp Algorithm for Pattern Searching
    Given two strings text and pattern string, your task is to find all starting positions where the pattern appears as a substring within the text. The strings will only contain lowercase English alphabets.While reporting the results, use 1-based indexing (i.e., the first character of the text is at po
    12 min read
    KMP Algorithm for Pattern Searching
    Given two strings txt and pat, the task is to return all indices of occurrences of pat within txt. Examples:Input: txt = "abcab", pat = "ab"Output: [0, 3]Explanation: The string "ab" occurs twice in txt, first occurrence starts from index 0 and second from index 3.Input: txt= "aabaacaadaabaaba", pat
    14 min read
    Z algorithm (Linear time pattern searching Algorithm)
    This algorithm efficiently locates all instances of a specific pattern within a text in linear time. If the length of the text is "n" and the length of the pattern is "m," then the total time taken is O(m + n), with a linear auxiliary space. It is worth noting that the time and auxiliary space of th
    13 min read
    Finite Automata algorithm for Pattern Searching
    Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m.Examples: Input: txt[] = "THIS IS A TEST TEXT" pat[] = "TEST" Output: Pattern found at index 10 Input: txt[] = "AABAACAADAAB
    13 min read
    Boyer Moore Algorithm for Pattern Searching
    Pattern searching is an important problem in computer science. When we do search for a string in a notepad/word file, browser, or database, pattern searching algorithms are used to show the search results. A typical problem statement would be- " Given a text txt[0..n-1] and a pattern pat[0..m-1] whe
    15+ min read
    Aho-Corasick Algorithm for Pattern Searching
    Given an input text and an array of k words, arr[], find all occurrences of all words in the input text. Let n be the length of text and m be the total number of characters in all words, i.e. m = length(arr[0]) + length(arr[1]) + ... + length(arr[k-1]). Here k is total numbers of input words. Exampl
    15+ min read
    ­­kasai’s Algorithm for Construction of LCP array from Suffix Array
    Background Suffix Array : A suffix array is a sorted array of all suffixes of a given string. Let the given string be "banana". 0 banana 5 a1 anana Sort the Suffixes 3 ana2 nana ----------------> 1 anana 3 ana alphabetically 0 banana 4 na 4 na 5 a 2 nanaThe suffix array for "banana" :suffix[] = {
    15+ min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences