#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;
class TrieNode {
public:
unordered_map<char, TrieNode*> children;
bool isEndOfWord = false;
};
class Trie {
private:
TrieNode* root;
void dfs(TrieNode* node, string prefix, vector<string>& results) {
if (node->isEndOfWord) {
results.push_back(prefix);
}
for (auto& child : node->children) {
dfs(child.second, prefix + child.first, results); // explore deeper
}
}
public:
Trie() {
root = new TrieNode();
}
void insert(const string& word) {
TrieNode* curr = root;
for (char c : word) {
if (curr->children.find(c) == curr->children.end()) {
curr->children[c] = new TrieNode(); // create node if missing
}
curr = curr->children[c]; // move to next node
}
curr->isEndOfWord = true; // mark word end
}
vector<string> autocomplete(const string& prefix) {
TrieNode* curr = root;
for (char c : prefix) {
if (curr->children.find(c) == curr->children.end()) {
return {}; // prefix not found
}
curr = curr->children[c]; // move to prefix node
}
vector<string> results;
dfs(curr, prefix, results); // collect all words
return results;
}
};
int main() {
Trie trie;
vector<string> words = {"cat", "car", "cap"};
for (const string& w : words) {
trie.insert(w);
}
string prefix = "ca";
vector<string> results = trie.autocomplete(prefix);
for (const string& word : results) {
cout << word << "\n";
}
return 0;
}
if (curr->children.find(c) == curr->children.end()) {
curr->children[c] = new TrieNode(); // create node if missing
}
create new node only if letter path does not exist to share prefixes
curr = curr->children[c]; // move to next node
advance current pointer to next letter node
curr->isEndOfWord = true; // mark word end
mark node as end of a valid word
if (curr->children.find(c) == curr->children.end()) {
return {}; // prefix not found
}
stop search early if prefix path missing
dfs(curr, prefix, results); // collect all words
explore all descendant nodes to find completions