-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathphrase_bkforest.go
92 lines (76 loc) · 2.39 KB
/
phrase_bkforest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package libgochewing
import (
"errors"
)
type PhraseBKForest struct {
tree map[int]*PhraseBKTreeNode
}
type PhraseBKTreeNode struct {
children map[int]*PhraseBKTreeNode
phraseArrayItem *PhraseArrayItem
}
func newPhraseBKForest() (phraseBKForest *PhraseBKForest) {
phraseBKForest = new(PhraseBKForest)
phraseBKForest.tree = make(map[int]*PhraseBKTreeNode)
return phraseBKForest
}
func newPhraseBKTreeNode(phraseArrayItem *PhraseArrayItem) (phraseBKTreeNode *PhraseBKTreeNode) {
phraseBKTreeNode = new(PhraseBKTreeNode)
phraseBKTreeNode.children = make(map[int]*PhraseBKTreeNode)
phraseBKTreeNode.phraseArrayItem = phraseArrayItem
return phraseBKTreeNode
}
func (this *PhraseBKForest) insert(phraseArrayItem *PhraseArrayItem) (err error) {
length := len(phraseArrayItem.phoneSeq)
if this.tree[length] == nil {
this.tree[length] = newPhraseBKTreeNode(phraseArrayItem)
return nil
} else {
return this.tree[length].insert(phraseArrayItem)
}
}
func (this *PhraseBKTreeNode) insert(phraseArrayItem *PhraseArrayItem) (err error) {
distance := calculateHammingDistance(this.phraseArrayItem, phraseArrayItem)
if distance == 0 {
return errors.New("Duplicate phoneSeq insert")
}
if this.children[distance] == nil {
this.children[distance] = newPhraseBKTreeNode(phraseArrayItem)
return nil
} else {
return this.children[distance].insert(phraseArrayItem)
}
}
func (this *PhraseBKForest) query(phoneSeq PhoneSeq, threshold int) (phraseArrayItem []*PhraseArrayItem) {
length := phoneSeq.getLength()
if this.tree[length] == nil {
return make([]*PhraseArrayItem, 0)
}
phraseArrayItem = make([]*PhraseArrayItem, 0, 1)
result := make(chan *PhraseArrayItem, 1000)
count := make(chan int, 1000)
counter := 1
go this.tree[length].query(phoneSeq, threshold, count, result)
for counter > 0 || len(result) > 0 {
select {
case res := <-result:
phraseArrayItem = append(phraseArrayItem, res)
case c := <-count:
counter += c
}
}
return phraseArrayItem
}
func (this *PhraseBKTreeNode) query(phoneSeq PhoneSeq, threshold int, count chan<- int, result chan<- *PhraseArrayItem) {
diff := calculateHammingDistance(phoneSeq, this.phraseArrayItem)
if diff <= threshold {
result <- this.phraseArrayItem
}
for i := diff - threshold; i <= diff+threshold; i++ {
if this.children[i] != nil {
count <- 1
go this.children[i].query(phoneSeq, threshold, count, result)
}
}
count <- -1
}