public class TrieNode { public Dictionary<char, TrieNode> Children = new Dictionary<char, TrieNode>(); public bool IsWord = false; } public class Trie { private TrieNode root = new TrieNode(); public void Insert(string word) { var node = root; foreach (var ch in word) { if (!node.Children.ContainsKey(ch)) { node.Children[ch] = new TrieNode(); } node = node.Children[ch]; } node.IsWord = true; } public bool SearchPrefix(string prefix) { var node = root; foreach (var ch in prefix) { if (!node.Children.ContainsKey(ch)) { return false; } node = node.Children[ch]; } return true; } } var trie = new Trie(); trie.Insert("cat"); trie.Insert("car"); trie.Insert("dog"); Console.WriteLine(trie.SearchPrefix("ca")); Console.WriteLine(trie.SearchPrefix("do")); Console.WriteLine(trie.SearchPrefix("bat"));
The prefixes "ca" and "do" exist in the inserted words, so SearchPrefix returns true for them. "bat" does not exist, so it returns false.
The 'IsWord' boolean is set to true when a node represents the last character of a stored word, marking the end of that word.
public bool Search(string word) { var node = root; foreach (var ch in word) { if (node.Children[ch] == null) { return false; } node = node.Children[ch]; } return node.IsWord; }
Accessing a dictionary key directly without checking if it exists causes a KeyNotFoundException if the key is missing.
public void CollectWords(TrieNode node, string prefix, List<string> results) {
if (node.IsWord) {
results.Add(prefix);
}
foreach (var child in node.Children) {
CollectWords(child.Value, prefix + child.Key, results);
}
}The method adds the prefix to results only when the node marks the end of a word, then recursively explores all children to find all words starting with that prefix.
Tries store nodes for each character, which can consume more memory than hash maps, but they provide efficient prefix search capabilities, which hash maps do not.
