📖 Scenario: Imagine you are building a simple search feature for a phone contact list. You want to find all contacts that start with a certain prefix quickly.
🎯 Goal: You will create a small program that stores contact names and then finds all names starting with a given prefix using two methods: a Trie and a Hash Map. This will help you understand how these data structures work for prefix matching.
📋 What You'll Learn
Create a list of contact names
Create a prefix string to search
Implement prefix matching using a Trie
Implement prefix matching using a Hash Map
Print the matching contacts from both methods
💡 Why This Matters
🌍 Real World
Search features in phone contacts, autocomplete in search engines, and dictionary word lookups use prefix matching to quickly find relevant results.
💼 Career
Understanding Tries and Hash Maps for prefix matching is useful for software engineers working on search engines, text editors, and any application requiring fast lookup of strings.
Progress0 / 4 steps
1
Create the list of contacts
Create a std::vector<std::string> called contacts with these exact names: "Alice", "Bob", "Alfred", "Bobby", and "Alex".
DSA C++
Hint
Use std::vector<std::string> and initialize it with the exact names inside curly braces.
2
Create the prefix to search
Create a std::string variable called prefix and set it to "Al".
DSA C++
Hint
Use std::string prefix = "Al"; to create the prefix variable.
3
Implement prefix matching using a Trie
Implement a simple Trie class with insert and startsWith methods. Insert all contacts into the Trie. Then create a function getContactsWithPrefixTrie that returns a std::vector<std::string> of all contacts starting with prefix using the Trie.
DSA C++
Hint
Build a Trie with insert and startsWithNode methods. Use a depth-first search to collect all words starting with the prefix.
4
Print matching contacts from Trie and Hash Map
Print the contacts starting with prefix found by getContactsWithPrefixTrie. Then create a std::unordered_map<std::string, bool> called contactMap with all contacts as keys. Use a loop to find and print all contacts starting with prefix from contactMap.
DSA C++
Hint
Use getContactsWithPrefixTrie to get and print contacts from the Trie. Then create a std::unordered_map<std::string, bool> with all contacts and print those starting with prefix by checking if pair.first.find(prefix) == 0.
Practice
(1/5)
1. Which data structure is generally more efficient for checking if a prefix exists in a large set of strings?
easy
A. Linked List, because it stores elements in order
B. Hash Map, because it stores keys with constant time lookup
C. Array, because it allows sequential search of prefixes
D. Trie, because it stores prefixes explicitly and allows fast prefix search
Solution
Step 1: Understand prefix search requirements
Prefix search needs to quickly find if any string starts with a given prefix.
Step 2: Compare Trie and Hash Map for prefix search
Trie stores prefixes explicitly, allowing fast traversal to check prefixes. Hash Map stores full keys, so prefix search requires checking many keys or extra processing.
Final Answer:
Trie, because it stores prefixes explicitly and allows fast prefix search -> Option D
Quick Check:
Prefix search = Trie [OK]
Hint: Prefix search is fastest with Trie due to explicit prefix nodes [OK]
Common Mistakes:
Thinking hash map can do prefix search in constant time
Confusing prefix search with exact key search
Ignoring the need to check multiple keys in hash map
2. Which of the following is the correct way to declare a Trie node in C++ for lowercase English letters?
easy
A. struct TrieNode { TrieNode* children[26]; bool isEnd; };
B. struct TrieNode { map children; bool isEnd; };
C. struct TrieNode { vector<int> children; bool isEnd; };
D. struct TrieNode { unordered_map children; bool isEnd; };
Solution
Step 1: Identify correct children type for fixed alphabet
For lowercase English letters, fixed size array of 26 pointers is efficient.
Step 2: Check each option's children type
struct TrieNode { TrieNode* children[26]; bool isEnd; }; uses TrieNode* children[26], which is correct. struct TrieNode { map children; bool isEnd; }; uses map, which is valid but slower. Options A and C use incorrect types.
Confusing prefix existence with full word existence
Incorrect index calculation for characters
Not checking for null root pointer
5. You need to implement a system that supports fast prefix matching for millions of strings with dynamic insertions and lookups. Which approach is best and why?
Option A: Use a sorted array of strings and binary search for prefixes.
Option B: Use a Hash Map storing all strings and check prefixes by scanning keys.
Option C: Use a Trie for prefix matching.
Option D: Use a linked list of strings and linear search for prefixes.
hard
A. Sorted array, because binary search is fast for prefix queries
B. Hash Map, because it has constant time lookup for exact keys
C. Trie, because it provides efficient prefix search and dynamic insertions
D. Linked list, because it is simple to implement
Solution
Step 1: Analyze requirements for millions of strings with dynamic insertions
Dynamic insertions require efficient updates; prefix matching needs fast queries.
Step 2: Compare data structures for prefix matching and insertions
Trie supports fast prefix search and efficient insertions. Hash Map is fast for exact keys but slow for prefix. Sorted array requires costly insertions. Linked list is slow for both.
Final Answer:
Trie, because it provides efficient prefix search and dynamic insertions -> Option C
Quick Check:
Dynamic prefix search = Trie [OK]
Hint: For dynamic prefix search, Trie beats hash map and arrays [OK]
Common Mistakes:
Choosing hash map for prefix search without scanning keys
Ignoring insertion cost in sorted arrays
Underestimating linked list search time
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.