-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathnode.go
128 lines (111 loc) · 2.67 KB
/
node.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package suffixtree
import (
"sort"
)
type node struct {
/*
* The payload array used to store the data (indexes) associated with this node.
* In this case, it is used to store all property indexes.
*/
data []int
/**
* The set of edges starting from this node
*/
edges []*edge
/**
* The suffix link as described in Ukkonen's paper.
* if str is the string denoted by the path from the root to this, this.suffix
* is the node denoted by the path that corresponds to str without the first rune.
*/
suffix *node
}
/*
* getData returns the first numElements elements from the ones associated to this node.
*
* Gets data from the payload of both this node and its children, the string representation
* of the path to this node is a substring of the one of the children nodes.
*
* @param numElements the number of results to return. Use <=0 to get all
* @return the first numElements associated to this node and children
*/
func (n *node) getData(numElements int) (ret []int) {
if numElements > 0 {
if numElements > len(n.data) {
numElements -= len(n.data)
ret = n.data
} else {
ret = n.data[:numElements]
return
}
} else {
ret = n.data
}
// need to get more matches from child nodes. This is what may waste time
for _, edge := range n.edges {
data := edge.node.getData(numElements)
NEXTIDX:
for _, idx := range data {
for _, v := range ret {
if v == idx {
continue NEXTIDX
}
}
if numElements > 0 {
numElements--
}
ret = append(ret, idx)
}
if numElements == 0 {
break
}
}
return
}
// addRef adds the given index to the set of indexes associated with this
func (n *node) addRef(index int) {
if n.contains(index) {
return
}
n.addIndex(index)
// add this reference to all the suffixes as well
iter := n.suffix
for iter != nil {
if iter.contains(index) {
break
}
iter.addRef(index)
iter = iter.suffix
}
}
func (n *node) contains(index int) bool {
i := sort.SearchInts(n.data, index)
return i < len(n.data) && n.data[i] == index
}
func (n *node) addEdge(r rune, e *edge) {
if idx := n.search(r); idx == -1 {
n.edges = append(n.edges, e)
sort.Slice(n.edges, func(i, j int) bool { return n.edges[i].label[0] < n.edges[j].label[0] })
} else {
n.edges[idx] = e
}
}
func (n *node) getEdge(r rune) *edge {
idx := n.search(r)
if idx < 0 {
return nil
}
return n.edges[idx]
}
func (n *node) search(r rune) int {
idx := sort.Search(len(n.edges), func(i int) bool { return n.edges[i].label[0] >= r })
if idx < len(n.edges) && n.edges[idx].label[0] == r {
return idx
}
return -1
}
func (n *node) addIndex(idx int) {
n.data = append(n.data, idx)
}
func newNode() *node {
return &node{}
}