Match a pattern and String without using regular expressions - GeeksforGeeks

25 Jan, 2022
Given a string, find out if string follows a given pattern or not without using any regular expressions. Examples:  
Input: 
string - GraphTreesGraph
pattern - aba
Output: 
a->Graph
b->Trees

Input: 
string - GraphGraphGraph
pattern - aaa
Output: 
a->Graph

Input: 
string - GeeksforGeeks
pattern - GfG
Output: 
G->Geeks
f->for

Input: 
string - GeeksforGeeks
pattern - GG
Output: 
No solution exists
 
We can solve this problem with the help of Backtracking. For each character in the pattern, if the character is not seen before, we consider all possible sub-strings and recurse to see if it leads to the solution or not. We maintain a map that stores sub-string mapped to a pattern character. If pattern character is seen before, we use the same sub-string present in the map. If we found a solution, for each distinct character in the pattern, we print string mapped to it using our map.Below is C++ implementation of above idea – 
CPP
Java
Python3
Javascript
// C++ program to find out if string follows// a given pattern or not#include <bits/stdc++.h>using namespace std; /*  Function to find out if string follows a given    pattern or not     str - given string    n - length of given string    i - current index in input string    pat - given pattern    m - length of given pattern    j - current index in given pattern    map - stores mapping between pattern and string */bool patternMatchUtil(string str, int n, int i,                    string pat, int m, int j,                    unordered_map<char, string>& map){    // If both string and pattern reach their end    if (i == n && j == m)        return true;     // If either string or pattern reach their end    if (i == n || j == m)        return false;     // read next character from the pattern    char ch = pat[j];     // if character is seen before    if (map.find(ch)!= map.end())    {        string s = map[ch];        int len = s.size();         // consider next len characters of str        string subStr = str.substr(i, len);         // if next len characters of string str        // don't match with s, return false        if (subStr.compare(s))            return false;         // if it matches, recurse for remaining characters        return patternMatchUtil(str, n, i + len, pat, m,                                            j + 1, map);    }     // If character is seen for first time, try out all    // remaining characters in the string    for (int len = 1; len <= n - i; len++)    {        // consider substring that starts at position i        // and spans len characters and add it to map        map[ch] = str.substr(i, len);         // see if it leads to the solution        if (patternMatchUtil(str, n, i + len, pat, m,                                          j + 1, map))            return true;         // if not, remove ch from the map        map.erase(ch);    }     return false;} // A wrapper over patternMatchUtil()functionbool patternMatch(string str, string pat, int n, int m){    if (n < m)    return false;     // create an empty hashmap    unordered_map<char, string> map;     // store result in a boolean variable res    bool res = patternMatchUtil(str, n, 0, pat, m, 0, map);     // if solution exists, print the mappings    for (auto it = map.begin(); res && it != map.end(); it++)        cout << it->first << "->" << it->second << endl;     // return result    return res;} // Driver codeint main(){    string str = "GeeksforGeeks", pat = "GfG";     int n = str.size(), m = pat.size();     if (!patternMatch(str, pat, n, m))        cout << "No Solution exists";     return 0;}
import java.util.HashMap;import java.util.Map; class Main{  // Function to determine if given pattern matches with a string or not  public static boolean match(String str, int i,                              String pat, int j,                              Map<Character, String> map)  {    int n = str.length(), m = pat.length();     // base condition    if (n < m) {      return false;    }     // if both pattern and the string reaches end    if (i == n && j == m) {      return true;    }     // if either string or pattern reaches end    if (i == n || j == m) {      return false;    }     // consider next character from the pattern    char curr = pat.charAt(j);     // if the character is seen before    if (map.containsKey(curr))    {      String s = map.get(curr);      int k = s.length();       // ss stores next k characters of the given string      String ss;      if (i + k < str.length()) {        ss = str.substring(i, i + k);      } else {        ss = str.substring(i);      }       // return false if next k characters doesn't match with s      if (ss.compareTo(s) != 0) {        return false;      }       // recur for remaining characters if next k characters matches      return match(str, i + k, pat, j + 1, map);    }     // process all remaining characters in the string if current    // character is never seen before    for (int k = 1; k <= n - i; k++)    {      // insert substring formed by next k characters of the string      // into the map      map.put(curr, str.substring(i, i + k));       // check if it leads to the solution      if (match(str, i + k, pat, j + 1, map)) {        return true;      }       // else backtrack - remove current character from the map      map.remove(curr);    }     return false;  }   public static void main(String[] args)  {    // input string and pattern    String str = "GeeksforGeeks";    String pat = "GfG";     // create a map to store mappings between the pattern and string    Map<Character, String> map = new HashMap<>();     // check for solution    if (match(str, 0, pat, 0, map))    {      for (Map.Entry<Character, String> entry: map.entrySet()) {        System.out.println(entry.getKey() + "->" + entry.getValue());      }    }    else {      System.out.println("Solution doesn't exist");    }  }} //This code is contributed by Priyadarshini Kumari
# Function to determine if given pattern matches with a string or notdef match(str, pat, dict, i=0, j=0):     n = len(str)    m = len(pat)     # base condition    if n < m:        return False     # if both pattern and the string reaches end    if i == n and j == m:        return True     # if either string or pattern reaches end    if i == n or j == m:        return False     # consider next character from the pattern    curr = pat[j]     # if the character is seen before    if curr in dict:         s = dict[curr]        k = len(s)         # ss stores next k characters of the given string        if i + k < len(str):            ss = str[i:i + k]        else:            ss = str[i:]         # return false if next k characters doesn't match with s        if ss != s:            return False         # recur for remaining characters if next k characters matches        return match(str, pat, dict, i + k, j + 1)     # process all remaining characters in the string if current    # character is never seen before    for k in range(1, n - i + 1):         # insert substring formed by next k characters of the string        # into the dictionary        dict[curr] = str[i:i + k]         # check if it leads to the solution        if match(str, pat, dict, i + k, j + 1):            return True         # else backtrack - remove current character from the dictionary        dict.pop(curr)     return False  if __name__ == '__main__':     # input string and pattern    str = "GeeksforGeeks"    pat = "GfG"     # create a dictionary to store mappings between the pattern and string    dict = {}     # check for solution    if match(str, pat, dict):        print(dict)    else:        print("Solution doesn't exist") # This code is contributed by Priyadarshini Kumari
<script> // Javascript program to find out if string follows// a given pattern or not  /*  Function to find out if string follows a given    pattern or not     str - given string    n - length of given string    i - current index in input string    pat - given pattern    m - length of given pattern    j - current index in given pattern    map - stores mapping between pattern and string */function patternMatchUtil(str, n, i, pat, m, j, map) {    // If both string and pattern reach their end    if (i == n && j == m)        return true;     // If either string or pattern reach their end    if (i == n || j == m)        return false;     // read next character from the pattern    let ch = pat[j];     // if character is seen before    if (map.has(ch)) {        let s = map.get(ch);        let len = s.length;         // consider next len characters of str        let subStr = str.substr(i, len);         // if next len characters of string str        // don't match with s, return false        if (subStr != s)            return false;         // if it matches, recurse for remaining characters        return patternMatchUtil(str, n, i + len, pat, m,            j + 1, map);    }     // If character is seen for first time, try out all    // remaining characters in the string    for (let len = 1; len <= n - i; len++) {        // consider substring that starts at position i        // and spans len characters and add it to map        map.set(ch, str.substr(i, len));         // see if it leads to the solution        if (patternMatchUtil(str, n, i + len, pat, m, j + 1, map))            return true;         // if not, remove ch from the map        map.delete(ch);    }     return false;} // A wrapper over patternMatchUtil()functionfunction patternMatch(str, pat, n, m) {    if (n < m)        return false;     // create an empty hashmap    let map = new Map();     // store result in a boolean variable res    let res = patternMatchUtil(str, n, 0, pat, m, 0, map);     // if solution exists, print the mappings    console.log(map)    for (it of [...map.keys()].reverse())        document.write(it + "->" + map.get(it) + "<br>");     // return result    return res;} // Driver codelet str = "GeeksforGeeks", pat = "GfG"; let n = str.lengthlet m = pat.length; if (!patternMatch(str, pat, n, m))    document.write("No Solution exists");         // This code is contributed by saurabh_jaiswal.</script>
Output:  
f->for
G->Geeks
This article is contributed by Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
pawki
_saurabh_jaiswal
Backtracking
Backtracking
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Backtracking | Introduction
m Coloring Problem | Backtracking-5
Print all paths from a given source to a destination
Subset Sum | Backtracking-4
Backtracking to find all subsets
Combinational Sum
Print all permutations of a string in Java
Travelling Salesman Problem implementation using BackTracking
8 queen problem
Count all possible paths between two vertices