Open In App

Match a pattern and String without using regular expressions

Improve
Improve
Like Article
Like
Save
Share
Report

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




// 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()function
bool 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 code
int 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;
}


Java




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


Python3




# Function to determine if given pattern matches with a string or not
def 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


C#




// C# program to find out if string follows
// a given pattern or not
using System;
using System.Collections.Generic;
 
public class GFG  {
 
  /*  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 */
  static bool patternMatchUtil(string str, int n, int i,
                               string pat, int m, int j,
                               Dictionary<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.ContainsKey(ch)) {
      string s = map[ch];
      int len = s.Length;
      if (len <= n - i) {
 
        // consider next len characters of str
        string subStr = str.Substring(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);
      }
      else {
        return false;
      }
    }
 
    // 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.Substring(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.Remove(ch);
    }
    return false;
  }
 
  // A wrapper over patternMatchUtil()function
  static bool patternMatch(string str, string pat, int n, int m) {
    if (n < m)
      return false;
 
    // create an empty hashmap (Dictionary)
    Dictionary<char, string> map = new Dictionary<char, string>();
 
    // store result in a boolean variable res
    bool res = patternMatchUtil(str, n, 0, pat, m, 0, map);
 
    // if solution exists, print the mappings
    foreach (var item in map) {
      Console.WriteLine(item.Key + "->" + item.Value);
    }
 
    // return result
    return res;
  }
 
  // Driver Code
  static public void Main(string[] args) {
    string str = "GeeksforGeeks";
    string pat = "GfG";
    int n = str.Length;
    int m = pat.Length;
    if (!patternMatch(str, pat, n, m))
      Console.WriteLine("No Solution exists");
  }
}
 
// This Code is Contributed by Prasad Kandekar(prasad264)


Javascript




<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()function
function 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 code
let str = "GeeksforGeeks", pat = "GfG";
 
let n = str.length
let 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

Time complexity of this code is O(2^m), where m is the length of the pattern. This is because in the worst case, the algorithm may have to try all possible combinations of substrings of the string to find a match with the pattern. 

Space complexity is O(m), where m is the length of the pattern, as the mapping between the pattern and the string is stored in a hash map with m characters.

 



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