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
wordto each character in the patternpat, storing each assignment in the mapmp. Whenever a pattern character reappears, we don’t try new substrings but instead verify that the next segment ofwordmatches 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 = 0in the word andj = 0in the pattern, and an empty mapmp. - If both
iandjreach the ends ofwordandpat, returntrue; if only one does, returnfalse. - Let
ch = pat[j]. - If
chis already inmp, lets = mp[ch], and check that the substring ofwordstarting atiwith lengths.size()equalss; if not, returnfalse, otherwise recurse withi += s.size()andj++. - If
chis not yet inmp, build candidate substringscurby appending one more character at a time fromword[i]onward; for eachcur, setmp[ch] = curand recurse with advanced indices; if the recursive call returnstrue, propagate success; if not, erasemp[ch]and try a longercur. - In
patternMatch, call this utility starting at(0,0); if it returnstrue, collect each(char, string)pair frommpinto the result vector.
Below is given the implementation:
#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;
}
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());
}
}
}
}
# 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])
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);
}
}
}
}
// 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]));
}
Output
a : 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.