-
Notifications
You must be signed in to change notification settings - Fork 1
/
intstab.go
231 lines (186 loc) · 5.23 KB
/
intstab.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* integer stabbing. */
package intstab
import (
"container/list"
"fmt"
"math"
"sort"
)
/*
* Public
*/
type IntervalStabber interface {
Intersect(uint16) ([]*Interval, error)
}
func (ts *intStab) Intersect(query uint16) (results []*Interval, err error) {
return ts.stab(query)
}
func NewIntervalStabber(intervals IntervalSlice) (ts IntervalStabber, err error) {
ts = new(intStab)
err = ts.(*intStab).init(intervals)
if err != nil {
ts = nil
}
return
}
/*
* Private
*/
/*
* +1 to always allocate including zero (allows queries 0-65535 inclusive)
* Anything higher and the compiler stops it =)
*/
const maxN = math.MaxUint16 + 1
type intStab struct {
root *uniqueInterval
intervals map[int]*uniqueInterval
starts uniqueIntervalSlice
}
func (ts *intStab) init(intervals IntervalSlice) (err error) {
n := len(intervals)
ts.intervals = make(map[int]*uniqueInterval, n)
for id, val := range intervals {
if _, err = val.isValid(); err != nil {
return
}
ts.intervals[id] = &uniqueInterval{interval: val, id: id}
}
// Root is id(-1)
ts.root = &uniqueInterval{interval: &Interval{}, id: -1}
ts.precompute()
return
}
func (ts *intStab) precompute() {
ts.precomputeSmaller()
events := ts.buildEvents()
starts := make(uniqueIntervalSlice, maxN)
children := make(map[int]*list.List, len(ts.intervals)) // include space for root's children
l := list.New()
lmap := make(map[int]*list.Element)
// Use a sweep line to build the tree in O(n)
for q := 0; q < maxN; q++ {
if v := l.Back(); v != nil {
starts[q] = v.Value.(*uniqueInterval)
}
// For all events in reverse order
for i := len(events[q]) - 1; i >= 0; i-- {
a := events[q][i]
// Rightmost left
if int(a.interval.Start) == q &&
(starts[q] == nil ||
starts[q].id != a.id) { // Catch single ranges e.g. 45-45
starts[q] = a
// Save link to position in L
lmap[a.id] = l.PushBack(a)
} else { // a.interval.End == q
var parent *uniqueInterval
e := lmap[a.id]
if pred := e.Prev(); pred != nil {
// a has predecessor b
parent = pred.Value.(*uniqueInterval)
} else {
// root as Parent
parent = ts.root
}
// Calculate siblings
if kids := children[parent.id]; kids == nil {
children[parent.id] = list.New()
} else if leftChild := kids.Front(); leftChild != nil {
a.leftSibling = leftChild.Value.(*uniqueInterval)
}
a.parent = parent
children[parent.id].PushBack(a)
l.Remove(e)
}
}
}
ts.starts = starts
}
func (ts *intStab) buildEvents() []uniqueIntervalSlice {
events := make([]uniqueIntervalSlice, maxN)
// Get a sorted list from the intervals map
sorted := make(uniqueIntervalSlice, 0, len(ts.intervals))
for _, v := range ts.intervals {
sorted = append(sorted, v)
}
// Sort by starting values
sort.Sort(sorted)
// Build the events
for _, a := range sorted {
events[a.interval.End] = append(events[a.interval.End], a)
events[a.interval.Start] = append(events[a.interval.Start], a)
}
return events
}
/*
All the intervals with left endpoint l, except one such longest
interval a, are stored in a list called Smaller(a) (see Figure 1).
These lists are sorted by length in descending order, get a link to
a, and every element in them is removed from I. */
func (ts *intStab) precomputeSmaller() {
sm := make([]uniqueIntervalSlice, maxN)
for _, a := range ts.intervals {
sm[a.interval.Start] = append(sm[a.interval.Start], a)
}
// sort Q elements by length
for i, arr := range sm {
if l := len(arr); l > 1 {
// More than one interval with same start, link them together
// and keep the longest. Remove all the rest from interval list
sort.Sort(arr)
// remove the longest one (it should be the last one)
// set it's nextSmaller before removing
arr[l-1].nextSmaller = arr[l-2]
arr = arr[:l-1]
// Remove each remaining item from the intervals map
for i, x := range arr {
if i == 0 {
x.nextSmaller = nil
} else {
x.nextSmaller = arr[i-1]
}
delete(ts.intervals, x.id)
}
}
sm[i] = nil
}
}
func (ts *intStab) stab(q uint16) (results []*Interval, err error) {
if ts.starts == nil {
return nil, fmt.Errorf("Need to initialise before querying")
} else if len(ts.starts) <= int(q) {
return nil, fmt.Errorf("Query is out of range")
}
stack := NewStack()
for x := ts.starts[q]; x != nil && x.id != ts.root.id; x = x.parent {
ts.traverse(x, stack, q)
}
finalLen := stack.Len()
results = make(IntervalSlice, finalLen)
for i := 0; i < finalLen; i++ {
results[i] = stack.Pop().(*uniqueInterval).interval
}
return
}
func (ts *intStab) traverse(v *uniqueInterval, stack Stack, q uint16) {
stack.Push(v)
// Iterate over ts.smaller from largest to smallest
for w := v.nextSmaller; w != nil; w = w.nextSmaller {
if w.interval.End < q {
break
}
stack.Push(w)
}
/* Calculate rightmost path:
* The rightmost path R(v) of a node v ∈ V (S) is empty if v has no left
* sibling or its left sibling w is not stabbed. Otherwise, R(v) is the
* path from w to the rightmost stabbed node in the subtree of w in S. */
for next := v.leftSibling; next != nil; next = next.leftSibling {
// Check left siblings until they don't stab
if next.Stab(q) {
ts.traverse(next, stack, q)
} else {
break
}
}
}