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
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
Regex Tutorial - How to write Regular Expressions? A regular expression (regex) is a sequence of characters that define a search pattern. Here's how to write regular expressions: Start by understanding the special characters used in regex, such as ".", "*", "+", "?", and more.Choose a programming language or tool that supports regex, such as Python,
6 min read
Regular Expression Matching Given a text t and a pattern p where t consists of only lowercase English alphabets while p consists of lowercase English alphabets as well as special characters '.' and '*', the task is to implement a function to test regular expression such that:'.' Matches any single character.ââââ'*' Matches zer
14 min read
std::regex_match, std::regex_replace() | Regex (Regular Expression) In C++ Regex is the short form for âRegular expressionâ, which is often used in this way in programming languages and many different libraries. It is supported in C++11 onward compilers.Function Templates used in regex regex_match() -This function return true if the regular expression is a match against th
3 min read
String matches() Method in Java with Examples In Java, the matches() method in the String class checks if a string matches a specified regular expression. It is useful for validating input patterns and searching within strings. In this article, we will learn how to use the matches() method effectively in Java with examples to illustrate its fun
3 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. * --> Matches with 0 or more instances of any character or set o
9 min read
WildCard pattern matching having three symbols ( * , + , ? ) 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 â
14 min read
Check if a given pattern exists in a given string or not including wild cards * and . Given two strings text and pattern of length M and N respectively, The task is to check if the pattern matches the text or not. If found to be true, then print "Yes". Otherwise, print "No". Note: pattern can include the characters '*' and 'â¢' '*' matches zero or more occurrences of character right b
15+ 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