158 lines
2.7 KiB
Go
158 lines
2.7 KiB
Go
|
package curl2info
|
||
|
|
||
|
// TrieWord Trie 需要的Word接口
|
||
|
type TrieWord interface {
|
||
|
GetWord() string
|
||
|
}
|
||
|
|
||
|
// TrieStrWord 最简单的TrieWord 结构
|
||
|
type TrieStrWord string
|
||
|
|
||
|
// GetWord 获取单词
|
||
|
func (tsw *TrieStrWord) GetWord() string {
|
||
|
return (string)(*tsw)
|
||
|
}
|
||
|
|
||
|
// Trie 前缀树
|
||
|
type Trie struct {
|
||
|
isWord bool
|
||
|
value interface{}
|
||
|
char byte
|
||
|
prev *Trie
|
||
|
next map[byte]*Trie
|
||
|
}
|
||
|
|
||
|
// NewTrie Initialize your data structure here.
|
||
|
func NewTrie() *Trie {
|
||
|
return &Trie{next: make(map[byte]*Trie)}
|
||
|
}
|
||
|
|
||
|
// Insert a word into the trie.
|
||
|
func (trie *Trie) Insert(iword TrieWord) {
|
||
|
cur := trie
|
||
|
word := iword.GetWord()
|
||
|
l := len(word)
|
||
|
|
||
|
for i := 0; i < l; i++ {
|
||
|
c := word[i]
|
||
|
if next, ok := cur.next[c]; ok {
|
||
|
cur = next
|
||
|
} else {
|
||
|
create := NewTrie()
|
||
|
cur.next[c] = create
|
||
|
create.char = c
|
||
|
create.prev = cur
|
||
|
cur = create
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cur.isWord = true
|
||
|
cur.value = iword
|
||
|
}
|
||
|
|
||
|
// AllWords 所有单词
|
||
|
func (trie *Trie) AllWords() []string {
|
||
|
var result []string
|
||
|
for _, v := range trie.next {
|
||
|
look(v, "", &result)
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func look(cur *Trie, content string, result *[]string) {
|
||
|
content += string(cur.char)
|
||
|
if cur.isWord {
|
||
|
*result = append(*result, content)
|
||
|
}
|
||
|
for _, v := range cur.next {
|
||
|
look(v, content, result)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Remove 移除单词
|
||
|
func (trie *Trie) Remove(word string) {
|
||
|
cur := trie
|
||
|
l := len(word)
|
||
|
for i := 0; i < l; i++ {
|
||
|
c := word[i]
|
||
|
if next, ok := cur.next[c]; ok {
|
||
|
cur = next
|
||
|
} else {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if cur != nil {
|
||
|
cur.isWord = false
|
||
|
cur.value = nil
|
||
|
|
||
|
lastchar := cur.char
|
||
|
|
||
|
if len(cur.next) == 0 {
|
||
|
for cur.isWord != true && cur.prev != nil {
|
||
|
lastchar = cur.char
|
||
|
cur = cur.prev
|
||
|
if len(cur.next) > 1 {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
delete(cur.next, lastchar)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SearchMostPrefix Returns if the word is in the trie.
|
||
|
func (trie *Trie) SearchMostPrefix(iword TrieWord) interface{} {
|
||
|
cur := trie
|
||
|
word := iword.GetWord()
|
||
|
|
||
|
l := len(word)
|
||
|
|
||
|
var result interface{}
|
||
|
for i := 0; i < l; i++ {
|
||
|
c := word[i]
|
||
|
if next, ok := cur.next[c]; ok {
|
||
|
cur = next
|
||
|
if cur.isWord {
|
||
|
result = cur.value
|
||
|
}
|
||
|
} else {
|
||
|
return result
|
||
|
}
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// Match Returns if the word is in the trie.
|
||
|
func (trie *Trie) Match(iword TrieWord) interface{} {
|
||
|
cur := trie
|
||
|
word := iword.GetWord()
|
||
|
|
||
|
l := len(word)
|
||
|
for i := 0; i < l; i++ {
|
||
|
c := word[i]
|
||
|
if next, ok := cur.next[c]; ok {
|
||
|
cur = next
|
||
|
} else {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return cur.value
|
||
|
}
|
||
|
|
||
|
// StartsWith Returns if there is any word in the trie that starts with the given prefix. */
|
||
|
func (trie *Trie) StartsWith(prefix string) bool {
|
||
|
cur := trie
|
||
|
l := len(prefix)
|
||
|
for i := 0; i < l; i++ {
|
||
|
c := prefix[i]
|
||
|
if next, ok := cur.next[c]; ok {
|
||
|
cur = next
|
||
|
} else {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|