package main
import (
"fmt"
)
// TrieNode represents each node in the trie
type TrieNode struct {
children map[rune]*TrieNode
isEnd bool
}
// Trie structure with root node
type Trie struct {
root *TrieNode
}
// NewTrie creates a new empty trie
func NewTrie() *Trie {
return &Trie{root: &TrieNode{children: make(map[rune]*TrieNode)}}
}
// Insert adds a word to the trie
func (t *Trie) Insert(word string) {
curr := t.root
for _, ch := range word {
if curr.children[ch] == nil {
curr.children[ch] = &TrieNode{children: make(map[rune]*TrieNode)}
}
curr = curr.children[ch] // advance curr to next node
}
curr.isEnd = true // mark end of word
}
// collectWords collects all words under given node with prefix
func (t *Trie) collectWords(node *TrieNode, prefix string, results *[]string) {
if node.isEnd {
*results = append(*results, prefix) // found a word
}
for ch, child := range node.children {
t.collectWords(child, prefix+string(ch), results) // recurse children
}
}
// StartsWith finds all words starting with prefix
func (t *Trie) StartsWith(prefix string) []string {
curr := t.root
for _, ch := range prefix {
if curr.children[ch] == nil {
return []string{} // prefix not found
}
curr = curr.children[ch] // advance curr to prefix node
}
results := []string{}
t.collectWords(curr, prefix, &results) // collect all words below prefix
return results
}
func main() {
words := []string{"app", "apple", "art"}
prefix := "ap"
// Build trie
trie := NewTrie()
for _, w := range words {
trie.Insert(w)
}
// Search trie
trieResults := trie.StartsWith(prefix)
fmt.Print("Trie words with prefix '", prefix, "': ")
for i, w := range trieResults {
if i > 0 {
fmt.Print(" -> ")
}
fmt.Print(w)
}
fmt.Println()
// Hash map approach
hashMap := make(map[string]bool)
for _, w := range words {
hashMap[w] = true
}
fmt.Print("Hash Map words with prefix '", prefix, "': ")
first := true
for k := range hashMap {
if len(k) >= len(prefix) && k[:len(prefix)] == prefix {
if !first {
fmt.Print(", ")
}
fmt.Print(k)
first = false
}
}
fmt.Println()
}
curr = curr.children[ch] // advance curr to next node
advance curr to next node -- build path for word
curr.isEnd = true // mark end of word
mark node as end of a valid word
if curr.children[ch] == nil { return []string{} }
stop if prefix path missing
curr = curr.children[ch] // advance curr to prefix node
follow prefix path in trie
t.collectWords(curr, prefix, &results) // collect all words below prefix
gather all words starting with prefix
for k := range hashMap { if len(k) >= len(prefix) && k[:len(prefix)] == prefix { ... } }
check each key for prefix match in hash map
Trie words with prefix 'ap': app -> apple
Hash Map words with prefix 'ap': app, apple