Я пытаюсь реализовать простой полнотекстовый поиск в golang, но все мои реализации оказываются слишком медленными, чтобы преодолеть пороги.
Задача заключается в следующем:
Документы - это непустые строки из строчных слов, разделенные пробелами
Каждый документ имеет неявный идентификатор, равный его индексу во входном массиве
New () создает индекс
Search (): принимает запрос, который также является строкой строчных слов, разделенных пробелами, и возвращает отсортированный массив уникальных идентификаторов.документов, которые содержат все слова из запроса независимо от их порядка
Пример:
index := New([]string{
"this is the house that jack built", //: 0
"this is the rat that ate the malt", //: 1
})
index.Search("") // -> []
index.Search("in the house that jack built") // -> []
index.Search("malt rat") // -> [1]
index.Search("is this the") // -> [0, 1]
Я уже пытался реализовать:
двоичное дерево поиска для каждого документа и для всех документов вместе
три (дерево префиксов) для каждого документа и для всех документов все вместе
поиск по инвертированному индексу
дерево двоичного поиска (для всех документов):
type Tree struct {
m map[int]bool
word string
left *Tree
right *Tree
}
type Index struct {
tree *Tree
}
дерево двоичного поиска (дерево для каждого документа):
type Tree struct {
word string
left *Tree
right *Tree
}
type Index struct {
tree *Tree
index int
next *Index
}
trie(для всех документов):
type Trie struct {
m map[uint8]*Trie
end_node map[int]bool
}
type Index struct {
trie *Trie
}
три (для каждого документа):
type Trie struct {
m map[uint8]*Trie
end_node bool
}
type Index struct {
trie *Trie
index int
next *Index
}
инвертированный индекс:
type Index struct {
m map[string]map[int]bool
}
Новое и реализация поиска для инвертированного индекса:
// New creates a fulltext search index for the given documents
func New(docs []string) *Index {
m := make(map[string]map[int]bool)
for i := 0; i < len(docs); i++ {
words := strings.Fields(docs[i])
for j := 0; j < len(words); j++ {
if m[words[j]] == nil {
m[words[j]] = make(map[int]bool)
}
m[words[j]][i+1] = true
}
}
return &(Index{m})
}
// Search returns a slice of unique ids of documents that contain all words from the query.
func (idx *Index) Search(query string) []int {
if query == "" {
return []int{}
}
ret := make(map[int]bool)
arr := strings.Fields(query)
fl := 0
for i := range arr {
if idx.m[arr[i]] == nil {
return []int{}
}
if fl == 0 {
for value := range idx.m[arr[i]] {
ret[value] = true
}
fl = 1
} else {
tmp := make(map[int]bool)
for value := range ret {
if idx.m[arr[i]][value] == true {
tmp[value] = true
}
}
ret = tmp
}
}
ret_arr := []int{}
for value := range ret {
ret_arr = append(ret_arr, value-1)
}
sort.Ints(ret_arr)
return ret_arr
}
Я что-то не так делаю или есть лучший алгоритм поиска в golang?
Любая помощь приветствуется.