package main
import (
"fmt"
)
type TrieNode struct {
children map[rune]*TrieNode
isWord bool
}
func NewTrieNode() *TrieNode {
return &TrieNode{children: make(map[rune]*TrieNode)}
}
type Trie struct {
root *TrieNode
}
func NewTrie() *Trie {
return &Trie{root: NewTrieNode()}
}
func (t *Trie) Insert(word string) {
curr := t.root
for _, ch := range word {
if curr.children[ch] == nil {
curr.children[ch] = NewTrieNode()
}
curr = curr.children[ch]
}
curr.isWord = true
}
func (t *Trie) LongestWord() string {
var result string
var dfs func(node *TrieNode, path []rune)
dfs = func(node *TrieNode, path []rune) {
if node != t.root && !node.isWord {
return
}
if len(path) > len(result) || (len(path) == len(result) && string(path) < result) {
result = string(path)
}
for ch := 'a'; ch <= 'z'; ch++ {
if node.children[ch] != nil {
dfs(node.children[ch], append(path, ch))
}
}
}
dfs(t.root, []rune{})
return result
}
func main() {
words := []string{"a", "ap", "app", "appl", "apple", "apply"}
trie := NewTrie()
for _, w := range words {
trie.Insert(w)
}
fmt.Println(trie.LongestWord())
}
for _, ch := range word { if curr.children[ch] == nil { curr.children[ch] = NewTrieNode() } curr = curr.children[ch] }
Insert each character, creating nodes if missing, advancing current pointer
Mark end of inserted word as valid word
if node != t.root && !node.isWord { return }
Stop DFS if current node is not a word (prefix missing)
if len(path) > len(result) || (len(path) == len(result) && string(path) < result) { result = string(path) }
Update result if current path is longer or lex smaller when equal length
for ch := 'a'; ch <= 'z'; ch++ { if node.children[ch] != nil { dfs(node.children[ch], append(path, ch)) } }
DFS children in alphabetical order to ensure lex order