|
1 | 1 | package implement_trie_prefix_tree
|
2 | 2 |
|
3 | 3 | type Trie struct {
|
4 |
| - Prefix string |
5 |
| - IsEnd bool |
6 |
| - Children map[string]*Trie |
7 |
| - words map[string]bool |
| 4 | + children map[rune]*Trie |
| 5 | + isEnd bool |
| 6 | + |
| 7 | + words map[string]bool |
8 | 8 | }
|
9 | 9 |
|
10 | 10 | func Constructor() Trie {
|
11 |
| - return Trie{ |
12 |
| - words: make(map[string]bool), |
13 |
| - |
14 |
| - Children: make(map[string]*Trie)} |
| 11 | + return Trie{children: make(map[rune]*Trie), |
| 12 | + words: make(map[string]bool)} |
15 | 13 | }
|
16 | 14 |
|
17 | 15 | func (t *Trie) Insert(word string) {
|
| 16 | + |
18 | 17 | t.words[word] = true
|
19 |
| - if t.Prefix == "" && !t.IsEnd { |
20 |
| - t.Prefix = word |
21 |
| - t.IsEnd = true |
22 |
| - return |
23 |
| - } |
24 |
| - if t.Prefix == word { |
25 |
| - t.IsEnd = true |
26 |
| - return |
27 |
| - } |
28 |
| - prefixLen := CommonPrefixLen(t.Prefix, word) |
29 |
| - if len(t.Prefix) > prefixLen { |
30 |
| - t.split(prefixLen) |
31 |
| - } |
| 18 | + node := t |
| 19 | + for _, ch := range word { |
32 | 20 |
|
33 |
| - if len(word) > prefixLen { |
34 |
| - kid := t.findOrCreateKid(word[prefixLen : prefixLen+1]) |
35 |
| - kid.Insert(word[prefixLen+1:]) |
36 |
| - } else { |
37 |
| - t.IsEnd = true |
38 |
| - } |
39 |
| -} |
40 |
| -func (node *Trie) findOrCreateKid(char string) *Trie { |
41 |
| - kid, ok := node.Children[char] |
42 |
| - if ok { |
43 |
| - return kid |
| 21 | + if node.children[ch] == nil { |
| 22 | + var nt = Constructor() |
| 23 | + node.children[ch] = &nt |
| 24 | + } |
| 25 | + node = node.children[ch] |
44 | 26 | }
|
45 |
| - kidn := Constructor() |
46 |
| - |
47 |
| - node.Children[char] = &kidn |
48 |
| - return &kidn |
| 27 | + node.isEnd = true |
49 | 28 | }
|
50 |
| -func (node *Trie) split(n int) { |
51 | 29 |
|
52 |
| - node.Children = map[string]*Trie{} |
53 |
| - var kidn = Constructor() |
54 |
| - var ntn = &kidn |
55 |
| - ntn.Prefix = node.Prefix[n+1:] |
56 |
| - ntn.Children = node.Children |
57 |
| - ntn.IsEnd = node.IsEnd |
58 |
| - node.Children[node.Prefix[n:n+1]] = ntn |
59 |
| - node.Prefix = node.Prefix[:n] |
60 |
| - node.IsEnd = false |
| 30 | +func (t *Trie) SearchPrefix(prefix string) *Trie { |
| 31 | + node := t |
| 32 | + for _, ch := range prefix { |
61 | 33 |
|
| 34 | + if node.children[ch] == nil { |
| 35 | + return nil |
| 36 | + } |
| 37 | + node = node.children[ch] |
| 38 | + } |
| 39 | + return node |
62 | 40 | }
|
63 | 41 |
|
64 | 42 | func (t *Trie) Search(word string) bool {
|
65 | 43 | return t.words[word]
|
66 | 44 | }
|
67 | 45 |
|
68 | 46 | func (t *Trie) StartsWith(prefix string) bool {
|
69 |
| - var has = t.words[prefix] |
70 |
| - if has { |
71 |
| - return true |
72 |
| - } |
73 |
| - // fmt.Println(t.Prefix,t.IsEnd,t.Children,t.words) |
74 |
| - // fmt.Println(prefix) |
75 |
| - if len(prefix) == 0 { |
76 |
| - return true |
77 |
| - } |
78 |
| - if t.Prefix == prefix { |
79 |
| - return true |
80 |
| - } |
81 | 47 |
|
82 |
| - n := CommonPrefixLen(t.Prefix, prefix) |
83 |
| - if n == len(t.Prefix) { |
84 |
| - kid, found := t.Children[prefix[n:n+1]] |
85 |
| - if found { |
86 |
| - return kid.StartsWith(prefix[n+1:]) |
| 48 | + if t.words[prefix] { |
87 | 49 |
|
88 |
| - } |
89 |
| - } |
90 |
| - if n == len(prefix) { |
91 | 50 | return true
|
92 | 51 | }
|
93 |
| - return false |
94 |
| -} |
95 |
| -func CommonPrefixLen(s1, s2 string) int { |
96 |
| - n1, n2 := len(s1), len(s2) |
97 |
| - i := 0 |
98 |
| - for ; i < n1 && i < n2; i++ { |
99 |
| - if s1[i] != s2[i] { |
100 |
| - break |
101 |
| - } |
102 |
| - } |
103 |
| - return i |
| 52 | + return t.SearchPrefix(prefix) != nil |
104 | 53 | }
|
0 commit comments