Given a dictionary of words where each word follows CamelCase notation, The task is to print all words in the dictionary that match with a given pattern consisting of uppercase characters only.
Note: CamelCase is the practice of writing compound words or phrases such that each word or abbreviation begins with a capital letter. Common examples include: “PowerPoint” and “WikiPedia”, “GeeksForGeeks”, “CodeBlocks”, etc.
Examples:
Input: dict[] = [“Hi”, “Hello”, “HelloWorld”, “HiTech”, “HiGeek”, “HiTechWorld”, “HiTechCity”, “HiTechLab”], pattern =”HT”,
Output: [“HiTech”, “HiTechWorld”, “HiTechCity”, “HiTechLab”]
Input: dict[] = [“Hi”, “Hello”, “HelloWorld”, “HiTech”, “HiGeek”, “HiTechWorld”, “HiTechCity”, “HiTechLab”], pattern =”H”,
Output: [“Hi”, “Hello”, “HelloWorld”, “HiTech”, “HiGeek”, “HiTechWorld”, “HiTechCity”, “HiTechLab”]
Input: dict[] = [“Hi”, “Hello”, “HelloWorld”, “HiTech”, “HiGeek”, “HiTechWorld”, “HiTechCity”, “HiTechLab”], pattern = “HTC”,
Output: [“HiTechCity”]
Input: dict[] = [“WelcomeGeek”,”WelcomeToGeeksForGeeks”, “GeeksForGeeks”], pattern = “WTG”,
Output: [“WelcomeToGeeksForGeeks”]
Input: dict[] = [“WelcomeGeek”,”WelcomeToGeeksForGeeks”, “GeeksForGeeks”], pattern = “GFG”,
Output: [GeeksForGeeks]
Input: dict[] = [“WelcomeGeek”,”WelcomeToGeeksForGeeks”, “GeeksForGeeks”], pattern = “GG”,
Output: No match found
Find Pattern in Camelcase Notation using Trie:
Below is the idea to solve the problem:
Insert all dictionary keys into the Trie one by one. Here key refers to only Uppercase characters in original word in CamelCase notation.
- When encountering the key for the first time, mark the last node as leaf node and insert the complete word for that key into the vector associated with the leaf node.
- If encountering a key that is already in the trie, update the vector associated with the leaf node with current word.
After all dictionary words are processed, search for the pattern in the trie and print all words that match the pattern.
Follow the below steps to Implement the idea:
- Initialize a trie and insert Capital case letters in all the words in the trie.
- After inserting the word set bool isleaf to 1 and insert the word in the vector of string for the node of last character.
- Query for the pattern in trie and on the last character node of the pattern return the vector of strings.
Below is the implementation of the above idea:
C++
#include <bits/stdc++.h>
using namespace std;
#define ALPHABET_SIZE 26
struct TrieNode
{
TrieNode* children[ALPHABET_SIZE];
bool isLeaf;
list<string> word;
};
TrieNode* getNewTrieNode( void )
{
TrieNode* pNode = new TrieNode;
if (pNode)
{
pNode->isLeaf = false ;
for ( int i = 0; i < ALPHABET_SIZE; i++)
pNode->children[i] = NULL;
}
return pNode;
}
void insert(TrieNode* root, string word)
{
int index;
TrieNode* pCrawl = root;
for ( int level = 0; level < word.length(); level++)
{
if ( islower (word[level]))
continue ;
index = int (word[level]) - 'A' ;
if (!pCrawl->children[index])
pCrawl->children[index] = getNewTrieNode();
pCrawl = pCrawl->children[index];
}
pCrawl->isLeaf = true ;
(pCrawl->word).push_back(word);
}
void printAllWords(TrieNode* root)
{
if (root->isLeaf)
{
for (string str : root->word)
cout << str << endl;
}
for ( int i = 0; i < ALPHABET_SIZE; i++)
{
TrieNode* child = root->children[i];
if (child)
printAllWords(child);
}
}
bool search(TrieNode* root, string pattern)
{
int index;
TrieNode* pCrawl = root;
for ( int level = 0; level < pattern.length(); level++)
{
index = int (pattern[level]) - 'A' ;
if (!pCrawl->children[index])
return false ;
pCrawl = pCrawl->children[index];
}
printAllWords(pCrawl);
return true ;
}
void findAllWords(vector<string> dict, string pattern)
{
TrieNode* root = getNewTrieNode();
for (string word : dict)
insert(root, word);
if (!search(root, pattern))
cout << "No match found" ;
}
int main()
{
vector<string> dict = {
"Hi" , "Hello" , "HelloWorld" , "HiTech" , "HiGeek" ,
"HiTechWorld" , "HiTechCity" , "HiTechLab"
};
string pattern = "HT" ;
findAllWords(dict, pattern);
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CamelCase {
static final int ALPHABET_SIZE = 26 ;
static class TrieNode {
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
boolean isLeaf;
List<String> word;
public TrieNode() {
isLeaf = false ;
for ( int i = 0 ; i < ALPHABET_SIZE; i++)
children[i] = null ;
word = new ArrayList<String>();
}
}
static TrieNode root;
static void insert(String word) {
int index;
TrieNode pCrawl = root;
for ( int level = 0 ; level < word.length(); level++) {
if (Character.isLowerCase(word.charAt(level)))
continue ;
index = word.charAt(level) - 'A' ;
if (pCrawl.children[index] == null )
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
pCrawl.isLeaf = true ;
(pCrawl.word).add(word);
}
static void printAllWords(TrieNode root) {
if (root.isLeaf) {
for (String str : root.word)
System.out.println(str);
}
for ( int i = 0 ; i < ALPHABET_SIZE; i++) {
TrieNode child = root.children[i];
if (child != null )
printAllWords(child);
}
}
static boolean search(String pattern) {
int index;
TrieNode pCrawl = root;
for ( int level = 0 ; level < pattern.length(); level++) {
index = pattern.charAt(level) - 'A' ;
if (pCrawl.children[index] == null )
return false ;
pCrawl = pCrawl.children[index];
}
printAllWords(pCrawl);
return true ;
}
static void findAllWords(List<String> dict, String pattern)
{
root = new TrieNode();
for (String word : dict)
insert(word);
if (!search(pattern))
System.out.println( "No match found" );
}
public static void main(String args[]) {
List<String> dict = Arrays.asList( "Hi" , "Hello" ,
"HelloWorld" , "HiTech" , "HiGeek" ,
"HiTechWorld" , "HiTechCity" ,
"HiTechLab" );
String pattern = "HT" ;
findAllWords(dict, pattern);
}
}
|
Python3
import string
ALPHABET_SIZE = 26
class TrieNode:
def __init__( self ):
self .children = [ None ] * ALPHABET_SIZE
self .isLeaf = False
self .word = []
def getNewTrieNode():
pNode = TrieNode()
return pNode
def insert(root, word):
pCrawl = root
for level in range ( len (word)):
if word[level].islower():
continue
index = ord (word[level]) - ord ( 'A' )
if not pCrawl.children[index]:
pCrawl.children[index] = getNewTrieNode()
pCrawl = pCrawl.children[index]
pCrawl.isLeaf = True
(pCrawl.word).append(word)
def printAllWords(root):
if root.isLeaf:
for str in root.word:
print ( str )
for i in range (ALPHABET_SIZE):
child = root.children[i]
if child:
printAllWords(child)
def search(root, pattern):
pCrawl = root
for level in range ( len (pattern)):
index = ord (pattern[level]) - ord ( 'A' )
if not pCrawl.children[index]:
return False
pCrawl = pCrawl.children[index]
printAllWords(pCrawl)
return True
def findAllWords( dict , pattern):
root = getNewTrieNode()
for word in dict :
insert(root, word)
if not search(root, pattern):
print ( "No match found" )
if __name__ = = '__main__' :
dict = [
"Hi" , "Hello" , "HelloWorld" , "HiTech" , "HiGeek" ,
"HiTechWorld" , "HiTechCity" , "HiTechLab"
]
pattern = "HT"
findAllWords( dict , pattern)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int ALPHABET_SIZE = 26;
public class TrieNode
{
public TrieNode[] children = new
TrieNode[ALPHABET_SIZE];
public bool isLeaf;
public List<String> word;
public TrieNode()
{
isLeaf = false ;
for ( int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null ;
word = new List<String>();
}
}
static TrieNode root;
static void insert(String word)
{
int index;
TrieNode pCrawl = root;
for ( int level = 0;
level < word.Length; level++)
{
if ( char .IsLower(word[level]))
continue ;
index = word[level] - 'A' ;
if (pCrawl.children[index] == null )
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
pCrawl.isLeaf = true ;
(pCrawl.word).Add(word);
}
static void printAllWords(TrieNode root)
{
if (root.isLeaf)
{
foreach (String str in root.word)
Console.WriteLine(str);
}
for ( int i = 0; i < ALPHABET_SIZE; i++)
{
TrieNode child = root.children[i];
if (child != null )
printAllWords(child);
}
}
static bool search(String pattern)
{
int index;
TrieNode pCrawl = root;
for ( int level = 0;
level < pattern.Length;
level++)
{
index = pattern[level] - 'A' ;
if (pCrawl.children[index] == null )
return false ;
pCrawl = pCrawl.children[index];
}
printAllWords(pCrawl);
return true ;
}
static void findAllWords(List<String> dict,
String pattern)
{
root = new TrieNode();
foreach (String word in dict)
insert(word);
if (!search(pattern))
Console.WriteLine( "No match found" );
}
public static void Main(String []args)
{
List<String> dict = new List<String>{ "Hi" , "Hello" ,
"HelloWorld" , "HiTech" ,
"HiGeek" , "HiTechWorld" ,
"HiTechCity" , "HiTechLab" };
String pattern = "HT" ;
findAllWords(dict, pattern);
}
}
|
Javascript
const ALPHABET_SIZE = 26;
class TrieNode {
constructor() {
this .children = Array(ALPHABET_SIZE).fill( null );
this .isLeaf = false ;
this .word = [];
}
}
function getNewTrieNode() {
const pNode = new TrieNode();
return pNode;
}
function insert(root, word) {
let pCrawl = root;
for (let level = 0; level < word.length; level++) {
if (!word[level].match(/[A-Z]/)) {
continue ;
}
const index = word.charCodeAt(level) - 'A '.charCodeAt(0);
// If there is no node for this character, create a new one
if (!pCrawl.children[index]) {
pCrawl.children[index] = getNewTrieNode();
}
// Move the pointer to the child node
pCrawl = pCrawl.children[index];
}
// Mark the node as end of word
pCrawl.isLeaf = true;
// Store the word at this node
pCrawl.word.push(word);
}
// Function to print all the words stored at a TrieNode
function printAllWords(root) {
// If the node is end of word, print all the words stored at this node
if (root.isLeaf) {
root.word.forEach((str) => {
console.log(str);
});
}
// Traverse through all the children nodes
for (let i = 0; i < ALPHABET_SIZE; i++) {
const child = root.children[i];
// If there is a child node, call printAllWords for this node
if (child) {
printAllWords(child);
}
}
}
// Function to search for a pattern in Trie
function search(root, pattern) {
let pCrawl = root;
// Traverse through each character of the pattern
for (let level = 0; level < pattern.length; level++) {
// Get the index of the character
const index = pattern.charCodeAt(level) - ' A'.charCodeAt(0);
if (!pCrawl.children[index]) {
return false ;
}
pCrawl = pCrawl.children[index];
}
printAllWords(pCrawl);
return true ;
}
function findAllWords(dict, pattern) {
const root = getNewTrieNode();
dict.forEach((word) => {
insert(root, word);
});
if (!search(root, pattern)) {
console.log( "No match found" );
}
}
const dict = [ "Hi" , "Hello" , "HelloWorld" , "HiTech" , "HiGeek" , "HiTechWorld" , "HiTechCity" , "HiTechLab" ];
const pattern = "HT" ;
findAllWords(dict, pattern);
|
Output
HiTech
HiTechCity
HiTechLab
HiTechWorld
Time complexity: O(n*m) where m is the length of the pattern and n is the length of the dictionary.
Auxiliary Space: O(n)
Another Approach: Two Pointer
Approach/Intuition:
Here, we are checking if the current word matches with the pattern or not. If it matches then we store that string. For checking we are using two pointer approach:
- If the character in ‘s’ matches the current character in ‘pattern’, then the function moves on to the next character in ‘pattern’.
- If the character in ‘s’ is uppercase and does not match the current character in ‘pattern’, then the returns false. Returns true if it has reached the end of ‘s’ and matched every character in ‘pattern’, and false otherwise.
Follow the below steps to Implement the idea:
- Create an empty vector to store the words that match with the given pattern.
- For each word in Dictionary, it checks whether the word matches with pattern. If it does, insert that string in the answer and return the vector.
- In “check” function Initializes an integer “j” to 0, representing the current index of the pattern “pattern” that we are matching against
- If the character in “s” matches the current character in “pattern”, then increment “j” to move on to the next character in “pattern”.
- If the character in “s” is uppercase and does not match the current character in “pattern”, then return false because it means we have encountered an uppercase letter in “s” that does not match the corresponding character in “pattern”.
- Returns true if we have reached the end of “s” and matched every character in “pattern”, and false otherwise
Below is the code to implement the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool check(string& s, string& pattern)
{
int j = 0;
int n = s.size();
int m = pattern.size();
for ( int i = 0; i < n; i++) {
if (s[i] == pattern[j]) {
j++;
}
else if ( isupper (s[i]) && j != m) {
return false ;
}
}
return j == m;
}
vector<string> CamelCase(vector<string> dict,
string pattern)
{
vector<string> ans;
for ( auto word : dict) {
if (check(word, pattern)) {
ans.push_back(word);
}
}
return ans;
}
int main()
{
vector<string> dict
= { "Hi" , "Hello" , "HelloWorld" ,
"HiTech" , "HiGeek" , "HiTechWorld" ,
"HiTechCity" , "HiTechLab" };
string pattern = "HT" ;
vector<string> ans = CamelCase(dict, pattern);
for ( auto word : ans) {
cout << word << endl;
}
return 0;
}
|
Java
import java.util.*;
class Main {
static boolean check(String s, String pattern) {
int j = 0 ;
int n = s.length();
int m = pattern.length();
for ( int i = 0 ; i < n; i++) {
if (j<m && s.charAt(i) == pattern.charAt(j)) {
j++;
} else if (Character.isUpperCase(s.charAt(i)) && j != m) {
return false ;
}
}
return j == m;
}
static List<String> CamelCase(List<String> dict, String pattern) {
List<String> ans = new ArrayList<>();
for (String word : dict) {
if (check(word, pattern)) {
ans.add(word);
}
}
return ans;
}
public static void main(String[] args) {
List<String> dict = Arrays.asList( "Hi" , "Hello" , "HelloWorld" ,
"HiTech" , "HiGeek" , "HiTechWorld" , "HiTechCity" , "HiTechLab" );
String pattern = "HT" ;
List<String> ans = CamelCase(dict, pattern);
for (String word : ans) {
System.out.println(word);
}
}
}
|
Python3
def check(s, pattern):
j = 0
n = len (s)
m = len (pattern)
for i in range (n):
if j<m and s[i] = = pattern[j]:
j + = 1
elif s[i].isupper() and j ! = m:
return False
return j = = m
def CamelCase( dict , pattern):
ans = []
for word in dict :
if check(word, pattern):
ans.append(word)
return ans
if __name__ = = '__main__' :
dict = [ "Hi" , "Hello" , "HelloWorld" , "HiTech" ,
"HiGeek" , "HiTechWorld" , "HiTechCity" , "HiTechLab" ]
pattern = "HT"
ans = CamelCase( dict , pattern)
for word in ans:
print (word)
|
C#
using System;
using System.Collections.Generic;
class Program
{
static bool Check( string s, string pattern)
{
int j = 0;
int n = s.Length;
int m = pattern.Length;
for ( int i = 0; i < n; i++)
{
if (j < m && s[i] == pattern[j])
{
j++;
}
else if ( char .IsUpper(s[i]) && j != m)
{
return false ;
}
}
return j == m;
}
static List< string > CamelCase(List< string > dict, string pattern)
{
List< string > ans = new List< string >();
foreach ( string word in dict)
{
if (Check(word, pattern))
{
ans.Add(word);
}
}
return ans;
}
public static void Main( string [] args)
{
List< string > dict = new List< string > {
"Hi" , "Hello" , "HelloWorld" , "HiTech" , "HiGeek" , "HiTechWorld" , "HiTechCity" , "HiTechLab"
};
string pattern = "HT" ;
List< string > ans = CamelCase(dict, pattern);
foreach ( string word in ans)
{
Console.WriteLine(word);
}
}
}
|
Javascript
function check(s, pattern) {
let j = 0;
const n = s.length;
const m = pattern.length;
for (let i = 0; i < n; i++) {
if (s[i] === pattern[j]) {
j++;
} else if (s[i].toUpperCase() === s[i] && j !== m) {
return false ;
}
}
return j === m;
}
function CamelCase(dict, pattern) {
const ans = [];
for (const word of dict) {
if (check(word, pattern)) {
ans.push(word);
}
}
return ans;
}
function main() {
const dict = [ "Hi" , "Hello" , "HelloWorld" , "HiTech" , "HiGeek" , "HiTechWorld" , "HiTechCity" , "HiTechLab" ];
const pattern = "HT" ;
const ans = CamelCase(dict, pattern);
for (const word of ans) {
console.log(word);
}
}
main();
|
Output
HiTech
HiTechWorld
HiTechCity
HiTechLab
Time complexity: O(n * m), where n is the number of words in the dictionary and m is the length of the pattern
Auxiliary Space: O(k), where k is the number of words in the dictionary that match the pattern
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
02 Dec, 2023
Like Article
Save Article