#include <iostream> #include <unordered_map> #include <string> using namespace std; class TrieNode { public: unordered_map<char, TrieNode*> children; bool isEndOfWord; TrieNode() : isEndOfWord(false) {} }; class Trie { private: TrieNode* root; public: Trie() { root = new TrieNode(); } void insert(const string& word) { TrieNode* node = root; for (char c : word) { if (!node->children.count(c)) { node->children[c] = new TrieNode(); } node = node->children[c]; } node->isEndOfWord = true; } bool startsWith(const string& prefix) { TrieNode* node = root; for (char c : prefix) { if (!node->children.count(c)) return false; node = node->children[c]; } return true; } }; int main() { Trie trie; trie.insert("apple"); trie.insert("app"); cout << boolalpha << trie.startsWith("app") << endl; cout << boolalpha << trie.startsWith("apl") << endl; return 0; }
The prefix "app" exists because both "apple" and "app" start with "app".
The prefix "apl" does not exist in the Trie because no inserted word starts with "apl".
Root node counts as 1.
Words share prefixes: "cat", "car", "cart" share 'c' and 'a' and 'r' nodes.
Counting nodes: root(1), c(2), a(3), t(4), r(5), t(6).
bool startsWith(const string& prefix) { TrieNode* node = root; for (char c : prefix) { node = node->children[c]; if (!node) return false; } return true; }
Using operator[] on unordered_map with a missing key inserts a new node, so node is never null.
Then dereferencing node->children[c] when node is null causes runtime error.
Option A is correct because it efficiently finds the prefix node and explores all descendants.
Other options are inefficient or incorrect.
#include <iostream> #include <unordered_map> #include <string> #include <vector> using namespace std; class TrieNode { public: unordered_map<char, TrieNode*> children; bool isEndOfWord; TrieNode() : isEndOfWord(false) {} }; class Trie { private: TrieNode* root; void dfs(TrieNode* node, string current, vector<string>& results) { if (node->isEndOfWord) results.push_back(current); for (auto& pair : node->children) { dfs(pair.second, current + pair.first, results); } } public: Trie() { root = new TrieNode(); } void insert(const string& word) { TrieNode* node = root; for (char c : word) { if (!node->children.count(c)) { node->children[c] = new TrieNode(); } node = node->children[c]; } node->isEndOfWord = true; } vector<string> findWordsWithPrefix(const string& prefix) { TrieNode* node = root; for (char c : prefix) { if (!node->children.count(c)) return {}; node = node->children[c]; } vector<string> results; dfs(node, prefix, results); return results; } }; int main() { Trie trie; trie.insert("test"); trie.insert("team"); trie.insert("teach"); trie.insert("toast"); vector<string> words = trie.findWordsWithPrefix("te"); for (const string& w : words) { cout << w << " "; } cout << endl; return 0; }
The DFS visits children in the order they were inserted: 's' for test, 'a' for team and teach.
So words collected are "test", "team", "teach" in that order.