Open In App

WildCard pattern matching having three symbols ( * , + , ? )

Last Updated : 15 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
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)
'+' – Matches previous single character
      of pattern 

Examples:

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

Input : Text = "aab"
Pattern = "*+"  output : false 
Pattern = "*+b" output : true    
  • Case 1: The character is ‘*’ Here two cases arise: We can ignore ‘*’ character and move to next character in the pattern. ‘*’ 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 ‘+’ Here two cases arise : We match current character of text with the previous character of pattern. If there is no previous character that mean ‘+’ is the first character of pattern so we print result as “text do not match”. If the previous character is either ‘+’, ‘?’ or ‘*’ we replace it with the last character used by them. 
  • Case 4: 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. 

The process for “*”, “?” is similar to wildcard pattern Matching for two characters:

Here we use a dp table that will contain 
two fields 
Struct DP
{
   // value is true if match possible
   // for current indexes, else false.
   bool value; 

   // Stores the character used 
   // by the symbol that we used 
   // later for symbol '+'
   char ch; 
}  

Below c++ implementation of above idea. 

CPP




// C++ program to implement wildcard
// pattern matching algorithm
#include <bits/stdc++.h>
using namespace std;
 
struct DP {
    bool value;
    char ch;
};
 
// Function that matches input str with
// given wildcard pattern
bool strmatch(string str, string pattern,
            int n, int m)
{
    // empty pattern can only match with
    // empty string
    if (m == 0)
        return (n == 0);
 
    // If first character of pattern is '+'
    if (pattern[0] == '+')
        return false;
 
    // lookup table for storing results of
    // subproblems
    struct DP lookup[m + 1][n + 1];
 
    // initialize lookup table to false
    for (int i = 0; i <= m; i++)
        for (int j = 0; j <= n; j++) {
            lookup[i][j].value = false;
            lookup[i][j].ch = ' ';
        }
         
    // empty pattern can match with
    // empty string
    lookup[0][0].value = true;
 
    // Only '*' can match with empty string
    for (int j = 1; j <= n; j++)
        if (pattern[j - 1] == '*')
            lookup[j][0].value =
                lookup[j - 1][0].value;
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; 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] == '*') {
                lookup[i][j].value =
                    lookup[i][j - 1].value ||
                    lookup[i - 1][j].value;
                lookup[i][j].ch = str[j - 1];
            }
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            else if (pattern[i - 1] == '?') {
                lookup[i][j].value =
                        lookup[i - 1][j - 1].value;
                lookup[i][j].ch = str[j - 1];
            }
 
            // (b) characters actually match
            else if (str[j - 1] == pattern[i - 1])
                lookup[i][j].value =
                    lookup[i - 1][j - 1].value;
 
            // Current character match
            else if (pattern[i - 1] == '+')
 
                // case 1: if previous character is
                // not symbol
                if (pattern[i - 2] != '+' ||
                    pattern[i - 2] != '*' ||
                    pattern[i - 2] != '?')
                    if (pattern[i - 2] == str[j - 1]) {
                        lookup[i][j].value =
                        lookup[i - 1][j - 1].value;
                        lookup[i][j].ch = str[j - 1];
                    }
 
                    // case 2 : if previous character
                    // is symbol (+, *, ? ) then we
                    // compare current text character
                    // with the character that is used by
                    // the symbol at that point. we
                    // access it by lookup[i-1][j-1]
                    else if (str[j-1] == lookup[i-1][j-1].ch) {
                        lookup[i][j].value =
                            lookup[i - 1][j - 1].value;
                        lookup[i][j].ch =
                            lookup[i - 1][j - 1].ch;
                    }
 
                    // If characters don't match
                    else
                        lookup[i][j].value = false;
        }
    }
 
    return lookup[m][n].value;
}
 
// Driver code
int main()
{
    string str = "baaabaaa";
    string pattern = "*****+ba***+";
 
    if (strmatch(str, pattern, str.length(),
                    pattern.length()))
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
 
    return 0;
}


Java




// Java code for the above approach
import java.util.Arrays;
 
class WildcardMatching {
    static class DP {
        boolean value;
        char ch;
    }
 
    // Function that matches input str with
    // given wildcard pattern
    static boolean strmatch(String str, String pattern)
    {
        int n = str.length();
        int m = pattern.length();
 
        // empty pattern can only match with
        // empty string
        if (m == 0)
            return (n == 0);
 
        // If first character of pattern is '+'
        if (pattern.charAt(0) == '+')
            return false;
 
        // lookup table for storing results of
        // subproblems
        DP[][] lookup = new DP[m + 1][n + 1];
 
        // initialize lookup table to false
        for (int i = 0; i <= m; i++)
            for (int j = 0; j <= n; j++) {
                lookup[i][j] = new DP();
                lookup[i][j].value = false;
                lookup[i][j].ch = ' ';
            }
 
        // empty pattern can match with
        // empty string
        lookup[0][0].value = true;
 
        // Only '*' can match with empty string
        for (int j = 1; j <= n; j++)
            if (pattern.charAt(j - 1) == '*')
                lookup[j][0].value = lookup[j - 1][0].value;
 
        // fill the table in bottom-up fashion
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; 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) == '*') {
                    lookup[i][j].value
                        = lookup[i][j - 1].value
                          || lookup[i - 1][j].value;
                    lookup[i][j].ch = str.charAt(j - 1);
                }
 
                // Current characters are considered as
                // matching in two cases
                // (a) current character of pattern is '?'
                else if (pattern.charAt(i - 1) == '?') {
                    lookup[i][j].value
                        = lookup[i - 1][j - 1].value;
                    lookup[i][j].ch = str.charAt(j - 1);
                }
 
                // (b) characters actually match
                else if (str.charAt(j - 1)
                         == pattern.charAt(i - 1))
                    lookup[i][j].value
                        = lookup[i - 1][j - 1].value;
 
                // Current character match
                else if (pattern.charAt(i - 1) == '+')
 
                    // case 1: if previous character is
                    // not symbol
                    if (pattern.charAt(i - 2) != '+'
                        || pattern.charAt(i - 2) != '*'
                        || pattern.charAt(i - 2) != '?')
                        if (pattern.charAt(i - 2)
                            == str.charAt(j - 1)) {
                            lookup[i][j].value
                                = lookup[i - 1][j - 1]
                                      .value;
                            lookup[i][j].ch
                                = str.charAt(j - 1);
                        }
 
                        // case 2 : if previous character
                        // is symbol (+, *, ? ) then we
                        // compare current text character
                        // with the character that is used
                        // by the symbol at that point. we
                        // access it by lookup[i-1][j-1]
                        else if (str.charAt(j - 1)
                                 == lookup[i - 1][j - 1]
                                        .ch) {
                            lookup[i][j].value
                                = lookup[i - 1][j - 1]
                                      .value;
                            lookup[i][j].ch
                                = lookup[i - 1][j - 1].ch;
                        }
 
                        // If characters don't match
                        else
                            lookup[i][j].value = false;
            }
        }
 
        return lookup[m][n].value;
    }
 
    public static void main(String[] args)
    {
        String str = "baaabaaa";
        String pattern = "*****+ba***+";
 
        if (strmatch(str, pattern))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
 
// This code is contributed by lokeshpotta20.


Python3




# Python program to implement wildcard
# pattern matching algorithm
 
class DP:
    def __init__(self, value, ch):
        self.value=value;
        self.ch=ch;
 
# Function that matches input str with
# given wildcard pattern
def strmatch( str,  pattern, n,  m):
    # empty pattern can only match with
    # empty string
    if (m == 0):
        return (n == 0);
 
    # If first character of pattern is '+'
    if (pattern[0] == '+'):
        return False;
 
    # lookup table for storing results of
    # subproblems
    lookup=[[0]*(n+1) for _ in range(m + 1)];
 
    # initialize lookup table to false
    for i in range(0,m+1):
        for j in range(0,n+1):
            lookup[i][j]=DP(False,' ');
 
    # empty pattern can match with
    # empty string
    lookup[0][0].value = True;
 
    # Only '*' can match with empty string
    for j in range(1,n+1):
        if (pattern[j - 1] == '*'):
            lookup[j][0].value = lookup[j - 1][0].value;
 
    # fill the table in bottom-up fashion
    for i in range(1,m+1):
        for j in range(1,n+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] == '*'):
                lookup[i][j].value = lookup[i][j - 1].value or lookup[i - 1][j].value;
                lookup[i][j].ch = str[j - 1];
 
            # Current characters are considered as
            # matching in two cases
            # (a) current character of pattern is '?'
            elif (pattern[i - 1] == '?'):
                lookup[i][j].value = lookup[i - 1][j - 1].value;
                lookup[i][j].ch = str[j - 1];
             
 
            # (b) characters actually match
            elif (str[j - 1] == pattern[i - 1]):
                lookup[i][j].value = lookup[i - 1][j - 1].value;
 
            # Current character match
            elif (pattern[i - 1] == '+'):
 
                # case 1: if previous character is
                # not symbol
                if (pattern[i - 2] != '+' or pattern[i - 2] != '*' or pattern[i - 2] != '?'):
                    if (pattern[i - 2] == str[j - 1]) :
                        lookup[i][j].value = lookup[i - 1][j - 1].value;
                        lookup[i][j].ch = str[j - 1];
                     
                    # case 2 : if previous character
                    # is symbol (+, *, ? ) then we
                    # compare current text character
                    # with the character that is used by
                    # the symbol at that point. we
                    # access it by lookup[i-1][j-1]
                    elif (str[j-1] == lookup[i-1][j-1].ch) :
                        lookup[i][j].value = lookup[i - 1][j - 1].value;
                        lookup[i][j].ch = lookup[i - 1][j - 1].ch;
                     
 
                    # If characters don't match
                    else:
                        lookup[i][j].value = False;
         
     
 
    return lookup[m][n].value;
 
 
# Driver code
str = "baaabaaa";
pattern = "*****+ba***+";
 
if (strmatch(str, pattern, len(str), len(pattern))):
    print("Yes");
else:
    print("No");


C#




// C# program to implement wildcard
// pattern matching algorithm
using System;
using System.Collections.Generic;
 
class Gfg
{
 
  class DP {
    public bool value;
    public char ch;
    public DP(bool value, char ch)
    {
      this.value=value;
      this.ch=ch;
    }
  }
 
  // Function that matches input str with
  // given wildcard pattern
  static bool strmatch(string str, string pattern, int n, int m)
  {
    // empty pattern can only match with
    // empty string
    if (m == 0)
      return (n == 0);
 
    // If first character of pattern is '+'
    if (pattern[0] == '+')
      return false;
 
    // lookup table for storing results of
    // subproblems
    DP[,] lookup=new DP[m+1, n+1];
    // initialize lookup table to false
    for (int i = 0; i <= m; i++)
    {
      for (int j = 0; j <= n; j++)
      {
        lookup[i,j]=new DP(false, ' ');
      }
    }
    // empty pattern can match with
    // empty string
    lookup[0,0].value = true;
 
    // Only '*' can match with empty string
    for (int j = 1; j <= n; j++)
      if (pattern[j - 1] == '*')
        lookup[j,0].value =
        lookup[j - 1,0].value;
 
    // fill the table in bottom-up fashion
    for (int i = 1; i <= m; i++) {
      for (int j = 1; j <= n; 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] == '*') {
          lookup[i,j].value =
            lookup[i,j - 1].value ||
            lookup[i - 1,j].value;
          lookup[i,j].ch = str[j - 1];
        }
 
        // Current characters are considered as
        // matching in two cases
        // (a) current character of pattern is '?'
        else if (pattern[i - 1] == '?') {
          lookup[i,j].value =
            lookup[i - 1,j - 1].value;
          lookup[i,j].ch = str[j - 1];
        }
 
        // (b) characters actually match
        else if (str[j - 1] == pattern[i - 1])
          lookup[i,j].value =
          lookup[i - 1,j - 1].value;
 
        // Current character match
        else if (pattern[i - 1] == '+')
 
          // case 1: if previous character is
          // not symbol
          if (pattern[i - 2] != '+' ||
              pattern[i - 2] != '*' ||
              pattern[i - 2] != '?')
            if (pattern[i - 2] == str[j - 1]) {
              lookup[i,j].value =
                lookup[i - 1,j - 1].value;
              lookup[i,j].ch = str[j - 1];
            }
 
        // case 2 : if previous character
        // is symbol (+, *, ? ) then we
        // compare current text character
        // with the character that is used by
        // the symbol at that point. we
        // access it by lookup[i-1,j-1]
        else if (str[j-1] == lookup[i-1,j-1].ch) {
          lookup[i,j].value =
            lookup[i - 1,j - 1].value;
          lookup[i,j].ch =
            lookup[i - 1,j - 1].ch;
        }
 
        // If characters don't match
        else
          lookup[i,j].value = false;
      }
    }
 
    return lookup[m,n].value;
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    string str = "baaabaaa";
    string pattern = "*****+ba***+";
 
    if (strmatch(str, pattern, str.Length, pattern.Length))
      Console.Write("Yes");
    else
      Console.Write("No");
  }
}
 
// This code is contributed by ratiagrawal.


Javascript




// Javascript program to implement wildcard
// pattern matching algorithm
 
class DP {
    constructor(value, ch) {
        this.value=value;
        this.ch=ch;
    }
}
 
// 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);
 
    // If first character of pattern is '+'
    if (pattern[0] == '+')
        return false;
 
    // lookup table for storing results of
    // subproblems
    let lookup = new DP(m+1);
     
    // initialize lookup table to false
    for (let i = 0; i <= m; i++){
        lookup[i]=new DP(n+1);
        for (let j = 0; j <= n; j++) {
            lookup[i][j]=new DP(false, ' ');
        }
    }
         
    // empty pattern can match with
    // empty string
    lookup[0][0].value = true;
 
    // Only '*' can match with empty string
    for (let j = 1; j <= n; j++)
        if (pattern[j - 1] == '*')
            lookup[j][0].value = lookup[j - 1][0].value;
 
    // fill the table in bottom-up fashion
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; 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] == '*') {
                lookup[i][j].value =
                    lookup[i][j - 1].value ||
                    lookup[i - 1][j].value;
                lookup[i][j].ch = str[j - 1];
            }
 
            // Current characters are considered as
            // matching in two cases
            // (a) current character of pattern is '?'
            else if (pattern[i - 1] == '?') {
                lookup[i][j].value =
                        lookup[i - 1][j - 1].value;
                lookup[i][j].ch = str[j - 1];
            }
 
            // (b) characters actually match
            else if (str[j - 1] == pattern[i - 1])
                lookup[i][j].value =
                    lookup[i - 1][j - 1].value;
 
            // Current character match
            else if (pattern[i - 1] == '+')
 
                // case 1: if previous character is
                // not symbol
                if (pattern[i - 2] != '+' ||
                    pattern[i - 2] != '*' ||
                    pattern[i - 2] != '?')
                    if (pattern[i - 2] == str[j - 1]) {
                        lookup[i][j].value =
                        lookup[i - 1][j - 1].value;
                        lookup[i][j].ch = str[j - 1];
                    }
 
                    // case 2 : if previous character
                    // is symbol (+, *, ? ) then we
                    // compare current text character
                    // with the character that is used by
                    // the symbol at that point. we
                    // access it by lookup[i-1][j-1]
                    else if (str[j-1] == lookup[i-1][j-1].ch) {
                        lookup[i][j].value =
                            lookup[i - 1][j - 1].value;
                        lookup[i][j].ch =
                            lookup[i - 1][j - 1].ch;
                    }
 
                    // If characters don't match
                    else
                        lookup[i][j].value = false;
        }
    }
 
    return lookup[m][n].value;
}
 
// Driver code
let str = "baaabaaa";
let pattern = "*****+ba***+";
 
if (strmatch(str, pattern, str.length,
                pattern.length))
    console.log("Yes");
else
    console.log("No");
 
 // This code is contributed by poojaagarwal2.


Output

Yes

Time Complexity : O(n*m)
Auxiliary Space: O(n*m)



Similar Reads

Dynamic Programming | Wildcard Pattern Matching | Linear Time and Constant Space
Given a text and a wildcard pattern, find 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) Pre-requisite: Dynamic Programming | W
19 min read
Wildcard Pattern Matching
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
42 min read
String matching where one string contains wildcard characters
Given two strings where first string may contain wild card characters and second string is a normal string. Write a function that returns true if the two strings match. The following are allowed wild card characters in first string. * --&gt; Matches with 0 or more instances of any character or set of characters. ? --&gt; Matches with any one charac
9 min read
Consonant and Vowel group check in String with Wildcard characters
Given a string S which is composed of lowercase alphabets and wildcard characters i.e. '?'. Here, '?' can be replaced by any of the lowercase alphabets, the task is to return 'True' if there are more than 3 consonants together or more than 5 vowels together else 'False'. Examples: Input: S = aeioup??Output: 0 Input: S = bcdaeiou??Output: 1 Approach
5 min read
CamelCase Pattern Matching
Given a list of words where each word follows CamelCase notation, the task is to print all words in the dictionary that match with a given pattern consisting of uppercase characters only. Examples Input: arr[] = [ "WelcomeGeek", "WelcomeToGeeksForGeeks", "GeeksForGeeks" ], pattern = "WTG" Output: WelcomeToGeeksForGeeks Explanation: There is only on
20 min read
Print all words matching a pattern in CamelCase Notation Dictionary
Given a dictionary of words where each word follows CamelCase notation, The task is to print all words in the dictionary that match with a given pattern consisting of uppercase characters only. Note: CamelCase is the practice of writing compound words or phrases such that each word or abbreviation begins with a capital letter. Common examples inclu
21 min read
Matching the Alphanumerical Pattern in Matrix I
Given a 2D integer matrix mat[][] and a 2D character matrix pat[][]. Where 0 &lt;= mat[r][c] &lt;= 9 and each element of pat is either a digit or a lowercase English letter. The task is to find a submatrix of mat that matches pat. An integer matrix part matches pat if we can replace cells containing letters in pat with some digits (each distinct le
12 min read
Number of quadruples where the first three terms are in AP and last three terms are in GP
Given an array arr[] of N integers. The task is to find the number of index quadruples (i, j, k, l) such that a[i], a[j] and a[k] are in AP and a[j], a[k] and a[l] are in GP. All the quadruples have to be distinct.Examples: Input: arr[] = {2, 6, 4, 9, 2} Output: 2 Indexes of elements in the quadruples are (0, 2, 1, 3) and (4, 2, 1, 3) and correspon
9 min read
Find three element from given three arrays such that their sum is X | Set 2
Given three sorted integer arrays A[], B[] and C[], the task is to find three integers, one from each array such that they sum up to a given target value X. Print Yes or No depending on whether such triplet exists or not.Examples: Input: A[] = {2}, B[] = {1, 6, 7}, C[] = {4, 5}, X = 12 Output: Yes A[0] + B[1] + C[0] = 2 + 6 + 4 = 12Input: A[] = {2}
9 min read
Find three closest elements from given three sorted arrays
Given three sorted arrays A[], B[] and C[], find 3 elements i, j and k from A, B and C respectively such that max(abs(A[i] - B[j]), abs(B[j] - C[k]), abs(C[k] - A[i])) is minimized. Here abs() indicates absolute value. Example : Input : A[] = {1, 4, 10} B[] = {2, 15, 20} C[] = {10, 12} Output: 10 15 10Explanation: 10 from A, 15 from B and 10 from C
21 min read