Match a pattern and String without using regular expressions
Last Updated :
11 May, 2025
Given two strings, word and pat, your task is to check if the string word follows the pattern of string pat. If the string follows the pattern, find the substring associated with each character of the given pattern string, else print -1.
Examples:
Input: word = "GraphTreesGraph", pat = "aba"
Output: a : Graph
b : Trees
Explanation: The character 'a' and 'b' of the pattern string can be mapped with substring "Graph" and "Trees" of the string word respectively.
Input: word = "GraphGraphGraph", pat = "aaa"
Output: a : Graph
Explanation: The character 'a' of the pattern string can be mapped with substring "Graph" of the string word.
Input: word = "GeeksforGeeks", pat = "gg"
Output: -1
Explanation: Since the pattern consists only of ‘g’ characters, a valid mapping would split the word into two identical halves—but those halves aren’t equal, so no solution exists.
Using Backtracking - O(n ^ m) Time and O(n + m) Space
The idea is to use backtracking to explore every way of assigning substrings of the input word
to each character in the pattern pat
, storing each assignment in the map mp
. Whenever a pattern character reappears, we don’t try new substrings but instead verify that the next segment of word
matches its existing mapping. If we manage to reach end of both the string, we’ve found a valid mapping.
Follow the below given steps:
- Begin with indices
i = 0
in the word and j = 0
in the pattern, and an empty map mp
. - If both
i
and j
reach the ends of word
and pat
, return true
; if only one does, return false
. - Let
ch = pat[j]
. - If
ch
is already in mp
, let s = mp[ch]
, and check that the substring of word
starting at i
with length s.size()
equals s
; if not, return false
, otherwise recurse with i += s.size()
and j++
. - If
ch
is not yet in mp
, build candidate substrings cur
by appending one more character at a time from word[i]
onward; for each cur
, set mp[ch] = cur
and recurse with advanced indices; if the recursive call returns true
, propagate success; if not, erase mp[ch]
and try a longer cur
. - In
patternMatch
, call this utility starting at (0,0)
; if it returns true
, collect each (char, string)
pair from mp
into the result vector.
Below is given the implementation:
CPP
#include <bits/stdc++.h>
using namespace std;
// recursive function to check all
// possible pattern - word mappings
bool patternMatchUtil(int i, int j, string &word,
string &pat, unordered_map<char, string> &mp) {
int n = word.size(), m = pat.size();
// 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 (mp.count(ch) != 0) {
// get the string mapped to the character
string s = mp[ch];
int len = s.size();
// consider next len characters of str
// check if they match with s
for(int k = 0; k < len; k++) {
if (i + k >= n || word[i + k] != s[k])
return false;
}
// if it matches,
// recurse for remaining characters
return patternMatchUtil(i + len, j + 1, word, pat, mp);
}
// if character is not seen before
// try all possible substrings of str
string cur = "";
for (int ind = i; ind < n; ind++) {
// add current character to the substring
cur += word[ind];
// map the character to the substring
mp[ch] = cur;
// see if it leads to the solution
if (patternMatchUtil(ind + 1, j + 1, word, pat, mp))
return true;
// if not, remove ch from the map
mp.erase(ch);
}
return false;
}
vector<pair<char, string>> patternMatch(string &word, string &pat) {
// to store the resultant pairs
vector<pair<char, string>> res;
// to store the character-word mappings
unordered_map<char, string> mp;
// check if the solution exists
bool ans = patternMatchUtil(0, 0, word, pat, mp);
// if the solution exists, store the mappings
if(ans) {
for (auto i:mp) {
res.push_back({i.first, i.second});
}
}
return res;
}
int main() {
string str = "GraphTreesGraph";
string pat = "aba";
vector<pair<char, string>> ans = patternMatch(str, pat);
if(ans.empty()) {
cout << -1;
}
else {
sort(ans.begin(), ans.end());
for(auto i: ans) {
cout << i.first << " : " << i.second << endl;
}
}
return 0;
}
Java
import java.util.*;
class GfG {
// recursive function to check all
// possible pattern - word mappings
static boolean patternMatchUtil(int i, int j, String word,
String pat, Map<Character, String> mp) {
int n = word.length(), m = pat.length();
// 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.charAt(j);
// if character is seen before
if (mp.containsKey(ch)) {
// get the string mapped to the character
String s = mp.get(ch);
int len = s.length();
// consider next len characters of str
// check if they match with s
for(int k = 0; k < len; k++) {
if (i + k >= n || word.charAt(i + k) != s.charAt(k))
return false;
}
// if it matches, recurse for remaining characters
return patternMatchUtil(i + len, j + 1, word, pat, mp);
}
// if character is not seen before
// try all possible substrings of str
String cur = "";
for (int ind = i; ind < n; ind++) {
// add current character to the substring
cur += word.charAt(ind);
// map the character to the substring
mp.put(ch, cur);
// see if it leads to the solution
if (patternMatchUtil(ind + 1, j + 1, word, pat, mp))
return true;
// if not, remove ch from the map
mp.remove(ch);
}
return false;
}
static List<AbstractMap.SimpleEntry<Character, String>>
patternMatch(String word, String pat) {
// to store the resultant pairs
List<AbstractMap.SimpleEntry<Character, String>> res =
new ArrayList<>();
// to store the character-word mappings
Map<Character, String> mp = new HashMap<>();
// check if the solution exists
boolean ans = patternMatchUtil(0, 0, word, pat, mp);
// if the solution exists, store the mappings
if(ans) {
for (Map.Entry<Character, String> i : mp.entrySet()) {
res.add(new AbstractMap.SimpleEntry<>
(i.getKey(), i.getValue()));
}
}
return res;
}
public static void main(String[] args) {
String str = "GraphTreesGraph";
String pat = "aba";
List<AbstractMap.SimpleEntry<Character, String>> ans =
patternMatch(str, pat);
if(ans.isEmpty()) {
System.out.print(-1);
} else {
for(AbstractMap.SimpleEntry<Character, String> i: ans) {
System.out.println(i.getKey() + " : " + i.getValue());
}
}
}
}
Python
# recursive function to check all
# possible pattern - word mappings
def patternMatchUtil(i, j, word, pat, mp):
n, m = len(word), len(pat)
# If both string and pattern reach their end
if i == n and j == m:
return True
# If either string or pattern reach their end
if i == n or j == m:
return False
# read next character from the pattern
ch = pat[j]
# if character is seen before
if ch in mp:
# get the string mapped to the character
s = mp[ch]
length = len(s)
# consider next len characters of str
# check if they match with s
for k in range(length):
if i + k >= n or word[i + k] != s[k]:
return False
# if it matches, recurse for remaining characters
return patternMatchUtil(i + length, j + 1, word, pat, mp)
# if character is not seen before
# try all possible substrings of str
cur = ""
for ind in range(i, n):
# add current character to the substring
cur += word[ind]
# map the character to the substring
mp[ch] = cur
# see if it leads to the solution
if patternMatchUtil(ind + 1, j + 1, word, pat, mp):
return True
# if not, remove ch from the map
del mp[ch]
return False
def patternMatch(word, pat):
# to store the resultant pairs
res = []
# to store the character-word mappings
mp = {}
# check if the solution exists
ans = patternMatchUtil(0, 0, word, pat, mp)
# if the solution exists, store the mappings
if ans:
for i in mp.items():
res.append((i[0], i[1]))
return res
if __name__ == "__main__":
str = "GraphTreesGraph"
pat = "aba"
ans = patternMatch(str, pat)
if not ans:
print(-1)
else:
for i in ans:
print(i[0], " : ", i[1])
C#
using System;
using System.Collections.Generic;
class GfG {
// recursive function to check all
// possible pattern - word mappings
static bool patternMatchUtil(int i, int j, string word,
string pat, Dictionary<char, string> mp) {
int n = word.Length, m = pat.Length;
// 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 (mp.ContainsKey(ch)) {
// get the string mapped to the character
string s = mp[ch];
int len = s.Length;
// consider next len characters of str
// check if they match with s
for(int k = 0; k < len; k++) {
if (i + k >= n || word[i + k] != s[k])
return false;
}
// if it matches, recurse for remaining characters
return patternMatchUtil(i + len, j + 1, word, pat, mp);
}
// if character is not seen before
// try all possible substrings of str
string cur = "";
for (int ind = i; ind < n; ind++) {
// add current character to the substring
cur += word[ind];
// map the character to the substring
mp[ch] = cur;
// see if it leads to the solution
if (patternMatchUtil(ind + 1, j + 1, word, pat, mp))
return true;
// if not, remove ch from the map
mp.Remove(ch);
}
return false;
}
static List<KeyValuePair<char, string>>
patternMatch(string word, string pat) {
// to store the resultant pairs
List<KeyValuePair<char, string>> res =
new List<KeyValuePair<char, string>>();
// to store the character-word mappings
Dictionary<char, string> mp =
new Dictionary<char, string>();
// check if the solution exists
bool ans = patternMatchUtil(0, 0, word, pat, mp);
// if the solution exists, store the mappings
if(ans) {
foreach (var i in mp) {
res.Add(new KeyValuePair<char, string>(i.Key, i.Value));
}
}
return res;
}
static void Main() {
string str = "GraphTreesGraph";
string pat = "aba";
var ans = patternMatch(str, pat);
if(ans.Count == 0) {
Console.Write(-1);
} else {
foreach(var i in ans) {
Console.WriteLine(i.Key + " : " + i.Value);
}
}
}
}
JavaScript
// recursive function to check all
// possible pattern - word mappings
function patternMatchUtil(i, j, word, pat, mp) {
const n = word.length, m = pat.length;
// 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
const ch = pat[j];
// if character is seen before
if (mp.hasOwnProperty(ch)) {
// get the string mapped to the character
const s = mp[ch];
const len = s.length;
// consider next len characters of str
// check if they match with s
for (let k = 0; k < len; k++) {
if (i + k >= n || word[i + k] !== s[k])
return false;
}
// if it matches, recurse for remaining characters
return patternMatchUtil(i + len, j + 1, word, pat, mp);
}
// if character is not seen before
// try all possible substrings of str
let cur = "";
for (let ind = i; ind < n; ind++) {
// add current character to the substring
cur += word[ind];
// map the character to the substring
mp[ch] = cur;
// see if it leads to the solution
if (patternMatchUtil(ind + 1, j + 1, word, pat, mp))
return true;
// if not, remove ch from the map
delete mp[ch];
}
return false;
}
function patternMatch(word, pat) {
// to store the resultant pairs
const res = [];
// to store the character-word mappings
const mp = {};
// check if the solution exists
const ans = patternMatchUtil(0, 0, word, pat, mp);
// if the solution exists, store the mappings
if(ans) {
for (const ch in mp) {
res.push([ch, mp[ch]]);
}
}
return res;
}
const str = "GraphTreesGraph";
const pat = "aba";
const ans = patternMatch(str, pat);
if(ans.length === 0) {
console.log(-1);
} else {
ans.forEach(i => console.log(i[0] + " : " + i[1]));
}
Outputa : Graph
b : Trees
Time Complexity: O(n ^ m), in the worst case, the recursive function will check for all possible combinations of string word and pat.
Space Complexity: O(n + m), to store the character - word mappings.
Similar Reads
Extracting all present dates in any given String using Regular Expressions
Given a string Str, the task is to extract all the present dates from the string. Dates can be in the format i.e., mentioned below: DD-MM-YYYYYYYY-MM-DDDD Month YYYY Examples: Input: Str = "The First Version was released on 12-07-2008.The next Release will come on 12 July 2009. The due date for paym
6 min read
Count occurrences of a word in string | Set 2 (Using Regular Expressions)
Given a string str and a word w, the task is to print the number of the occurrence of the given word in the string str using Regular Expression. Examples: Input: str = "peter parker picked a peck of pickled peppersâ, w = "peck"Output: 1Explanation: There is only one occurrence of the word "peck" in
4 min read
Find all the patterns of "1(0+)1" in a given string using Regular Expression
In Set 1, we have discussed general approach for counting the patterns of the form 1(0+)1 where (0+) represents any non-empty consecutive sequence of 0âs.In this post, we will discuss regular expression approach to count the same. Examples: Input : 1101001 Output : 2 Input : 100001abc101 Output : 2
3 min read
Extracting all Email Ids in any given String using Regular Expressions
Given a string str, the task is to extract all the Email ID's from the given string.Example:Input: "Please send your resumes to Hr@[email protected] for any business inquiry please mail us at business@[email protected]"Output: Hr@[email protected]@[email protected]
4 min read
Match flight number using Regular Expression
Given some Flight Numbers, the task is to check if they are valid or not using regular expressions. Rules for the valid flight numbers are: It is an alphanumeric string containing uppercase Alphabet letters(A-Z) and digits(0-9).It should always start with one of the alphabet letters and should end w
6 min read
How to validate a Username using Regular Expressions in Java
Given a string str which represents a username, the task is to validate this username with the help of Regular Expressions. A username is considered valid if all the following constraints are satisfied: The username consists of 6 to 30 characters inclusive. If the username consists of less than 6 or
3 min read
How to validate Visa Card number using Regular Expression
Given a string str, the task is to check whether the given string is a valid Visa Card number or not by using Regular Expression. The valid Visa Card number must satisfy the following conditions: It should be 13 or 16 digits long, new cards have 16 digits and old cards have 13 digits.It should start
6 min read
International Tracking of Exports validation using Regular Expression
Given some International Tracking Of Exports data, the task is to check if they are valid or not using regular expressions. Rules for the valid International Tracking Of Exports are : It is an alphanumeric string containing UpperCase letters and digits.It either follows the pattern 2 Letters(A-Z)+ 9
5 min read
Validating Voter ID Card using Regular Expression
Voter ID card is also known as EPIC (Electors Photo Identity Card). EPIC is an identification proof for Indian citizens over the age of 18.Given some Voter ids, the task is to check if they are valid or not using regular expressions. Rules for the valid VOTER ID: EPIC Number is a unique alphanumeric
6 min read
Find all strings that match specific pattern in a dictionary
Given a dictionary of words, find all strings that match the given pattern where every character in the pattern is uniquely mapped to a character in the dictionary. Examples: Input: dict = ["abb", "abc", "xyz", "xyy"]; pattern = "foo" Output: [xyy abb] xyy and abb have same character at index 1 and
15+ min read