suffix_tree 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/lib/data/base_data_source.rb +44 -0
  3. data/lib/data/data_source_factory.rb +16 -0
  4. data/lib/data/file_data_source.rb +29 -0
  5. data/lib/data/line_state_machine.rb +86 -0
  6. data/lib/data/string_data_source.rb +31 -0
  7. data/lib/data/word_data_source.rb +229 -0
  8. data/lib/location.rb +165 -0
  9. data/lib/node.rb +63 -0
  10. data/lib/node_factory.rb +169 -0
  11. data/lib/persist/suffix_tree_db.rb +148 -0
  12. data/lib/search/searcher.rb +68 -0
  13. data/lib/suffix_linker.rb +16 -0
  14. data/lib/suffix_tree.rb +122 -0
  15. data/lib/visitor/base_visitor.rb +17 -0
  16. data/lib/visitor/bfs.rb +22 -0
  17. data/lib/visitor/data_source_visitor.rb +15 -0
  18. data/lib/visitor/dfs.rb +34 -0
  19. data/lib/visitor/k_common_visitor.rb +71 -0
  20. data/lib/visitor/leaf_count_visitor.rb +15 -0
  21. data/lib/visitor/node_count_visitor.rb +16 -0
  22. data/lib/visitor/numbering_visitor.rb +230 -0
  23. data/lib/visitor/suffix_offset_visitor.rb +23 -0
  24. data/lib/visitor/tree_print_visitor.rb +44 -0
  25. data/lib/visitor/value_depth_visitor.rb +34 -0
  26. data/spec/constant_lca_spec.rb +27 -0
  27. data/spec/data_source_spec.rb +51 -0
  28. data/spec/fixtures/arizona.txt +1 -0
  29. data/spec/fixtures/chapter1.txt +371 -0
  30. data/spec/fixtures/chapter1.txt.summary +3 -0
  31. data/spec/fixtures/chapter1.txt.values +0 -0
  32. data/spec/fixtures/chapter1.txt.words +1329 -0
  33. data/spec/fixtures/mississippi.txt +1 -0
  34. data/spec/fixtures/singlePara.txt +41 -0
  35. data/spec/fixtures/smallFile.txt +3 -0
  36. data/spec/fixtures/smallFile.txt.summary +2 -0
  37. data/spec/fixtures/smallFile.txt.values +0 -0
  38. data/spec/fixtures/smallFile.txt.words +14 -0
  39. data/spec/fixtures/testbook.txt +5414 -0
  40. data/spec/location_spec.rb +149 -0
  41. data/spec/node_factory_spec.rb +199 -0
  42. data/spec/search_spec.rb +182 -0
  43. data/spec/suffix_tree_spec.rb +270 -0
  44. data/spec/util_spec.rb +47 -0
  45. data/spec/visitor_spec.rb +310 -0
  46. metadata +87 -0
@@ -0,0 +1,270 @@
1
+ require 'rspec'
2
+
3
+ require_relative '../lib/data/string_data_source'
4
+ require_relative '../lib/data/word_data_source'
5
+ require_relative '../lib/suffix_tree'
6
+ require_relative '../lib/visitor/data_source_visitor'
7
+ require_relative '../lib/visitor/dfs'
8
+ require_relative '../lib/visitor/leaf_count_visitor'
9
+ require_relative '../lib/visitor/tree_print_visitor'
10
+ require_relative '../lib/visitor/value_depth_visitor'
11
+
12
+
13
+ describe 'suffix tree' do
14
+
15
+ it 'should create suffix tree' do
16
+
17
+ st = SuffixTree.new('$')
18
+ stringData = StringDataSource.new("mississippi")
19
+ st.addDataSource(stringData)
20
+ expect(st.root).to_not eq(nil)
21
+ expect(st.root.children.length).to eq(5)
22
+ mChild = st.root.children['m']
23
+ expect(mChild).to_not eq(nil)
24
+ expect(mChild.isLeaf).to eq(true)
25
+ expect(mChild.suffixOffset).to eq(0)
26
+ iChild = st.root.children['i']
27
+ expect(iChild).to_not eq(nil)
28
+ expect(iChild.isInternal).to eq(true)
29
+ expect(iChild.children.length).to eq(3)
30
+ expect(iChild.suffixOffset).to eq(1)
31
+ sChild = st.root.children['s']
32
+ expect(sChild.isInternal).to eq(true)
33
+ expect(sChild.children.length).to eq(2)
34
+ pChild = st.root.children['p']
35
+ expect(pChild.isInternal).to eq(true)
36
+ expect(pChild.children.length).to eq(2)
37
+ end
38
+
39
+ it "builds tree with one leaf" do
40
+ dataSource = StringDataSource.new("a")
41
+ st = SuffixTree.new
42
+ st.addDataSource(dataSource)
43
+ expect(st.root.children.length).to eq (1)
44
+ location = st.location
45
+ expect(location.onNode).to eq (true)
46
+ expect(location.node).to eq(st.root)
47
+ end
48
+
49
+ it "builds tree with two leaf" do
50
+ dataSource = StringDataSource.new("ab")
51
+ st = SuffixTree.new
52
+ st.addDataSource(dataSource)
53
+ expect(st.root.children.length).to eq (2)
54
+ child1 = st.root.children['a']
55
+ expect(child1.suffixOffset).to eq(0)
56
+ child2 = st.root.children['b']
57
+ expect(child2.suffixOffset).to eq(1)
58
+ location = st.location
59
+ expect(location.onNode).to eq (true)
60
+ expect(location.node).to eq(st.root)
61
+ end
62
+
63
+ it "builds mississippi tree" do
64
+ dataSource = StringDataSource.new("mississippi")
65
+ st = SuffixTree.new
66
+ st.setDataSource(dataSource)
67
+
68
+ sio = StringIO.new()
69
+ tpv = TreePrintVisitor.new(dataSource, sio)
70
+ dfs = DFS.new(tpv)
71
+
72
+ st.addValue('m', 0)
73
+
74
+ expect(st.root.children['m'].nodeId).to eq(2)
75
+ location = st.location
76
+ expect(location.onNode).to eq (true)
77
+ expect(location.node.nodeId).to eq (1)
78
+
79
+ st.addValue('i', 1)
80
+
81
+ expect(st.root.children['i'].nodeId).to eq(3)
82
+ expect(location.onNode).to eq (true)
83
+ expect(location.node.nodeId).to eq (st.root.nodeId)
84
+
85
+ st.addValue('s', 2)
86
+
87
+ expect(st.root.children['s'].nodeId).to eq(4)
88
+ expect(location.onNode).to eq (true)
89
+ expect(location.node.nodeId).to eq (st.root.nodeId)
90
+
91
+ st.addValue('s', 3)
92
+
93
+ rootSchild = st.root.children['s']
94
+ expect(rootSchild.nodeId).to eq (4)
95
+ expect(rootSchild.incomingEdgeStartOffset).to eq(2)
96
+ expect(rootSchild.incomingEdgeEndOffset).to eq(Node::CURRENT_ENDING_OFFSET)
97
+ expect(location.onNode).to eq (false)
98
+ expect(location.incomingEdgeOffset).to eq (3)
99
+
100
+ st.addValue('i', 4)
101
+
102
+ # should have added an internal node and a leaf node
103
+ # internal node should be the 's' child of root, with a suffix link pointing to root
104
+ rootSchild = st.root.children['s']
105
+ expect(rootSchild.suffixLink).not_to eq (nil)
106
+ expect(rootSchild.suffixLink).to eq(st.root)
107
+ expect(location.onNode).to eq (false)
108
+ expect(location.incomingEdgeOffset).to eq (2)
109
+ rootSchild = st.root.children['s']
110
+ suffix3_nodeId = rootSchild.children['s'].nodeId
111
+ expect(rootSchild.incomingEdgeStartOffset).to eq(2)
112
+ expect(rootSchild.incomingEdgeEndOffset).to eq(2)
113
+
114
+ # these next 3 should not should only update the location incomingEdgeOffset
115
+ st.addValue('s', 5)
116
+
117
+ expect(location.incomingEdgeOffset).to eq (3)
118
+ expect(location.onNode).to eq (false)
119
+
120
+ st.addValue('s', 6)
121
+
122
+ expect(location.incomingEdgeOffset).to eq (4)
123
+ expect(location.onNode).to eq (false)
124
+
125
+ st.addValue('i', 7)
126
+
127
+ expect(location.incomingEdgeOffset).to eq (5)
128
+ expect(location.onNode).to eq (false)
129
+
130
+ result = st.extend('p', 8)
131
+
132
+ expect(result).to eq (true)
133
+ expect(location.onNode).to eq(true)
134
+ slNode = location.node
135
+ expect(slNode.suffixLink).to eq(nil)
136
+ result = st.extend('p', 8)
137
+
138
+ expect(result).to eq (true)
139
+ expect(location.onNode).to eq(false)
140
+ result = st.extend('p', 8)
141
+
142
+ expect(result).to eq (true)
143
+ expect(location.onNode).to eq(true)
144
+ expect(slNode.suffixLink).not_to eq(nil)
145
+ result = st.extend('p', 8)
146
+
147
+ expect(result).to eq (true)
148
+ expect(location.onNode).to eq(false)
149
+ result = st.extend('p', 8)
150
+
151
+ expect(result).to eq (true)
152
+ expect(location.onNode).to eq(true)
153
+ result = st.extend('p', 8)
154
+
155
+ expect(result).to eq (true)
156
+ expect(location.onNode).to eq(false)
157
+ result = st.extend('p', 8)
158
+
159
+ expect(result).to eq (true)
160
+ expect(location.onNode).to eq(true)
161
+ result = st.extend('p', 8)
162
+
163
+ expect(result).to eq (true)
164
+ expect(location.onNode).to eq(true)
165
+ result = st.extend('p', 8)
166
+
167
+ expect(result).to eq (false)
168
+ expect(location.onNode).to eq(true)
169
+
170
+ st.addValue('p', 9)
171
+
172
+ expect(location.onNode).to eq (false)
173
+ expect(location.incomingEdgeOffset).to eq(9)
174
+
175
+ st.addValue('i', 10)
176
+
177
+ dfs.traverse(st.root)
178
+ expected_tree = <<-TREESTR
179
+ ROOT
180
+ mississippi
181
+ i
182
+ ssi
183
+ ssippi
184
+ ppi
185
+ ppi
186
+ s
187
+ si
188
+ ssippi
189
+ ppi
190
+ i
191
+ ssippi
192
+ ppi
193
+ p
194
+ pi
195
+ i
196
+ TREESTR
197
+ expect(sio.string).to eq (expected_tree)
198
+
199
+ expect(location.onNode).to eq (true)
200
+ expect(location.node.nodeId).to eq (13)
201
+ end
202
+
203
+ it "builds suffix tree of words" do
204
+ wordDataSource = WordDataSource.new File.join('spec', 'fixtures', "chapter1.txt")
205
+ st = SuffixTree.new(nil, { :leafCount => true, :valueDepth => true })
206
+ st.addDataSource(wordDataSource)
207
+
208
+ root = st.root
209
+ expect(root.nodeId).to eq 1
210
+ lcv = DFS.new(LeafCountVisitor.new)
211
+ lcv.traverse(st.root)
212
+ deepVal = DeepestValueDepthVisitor.new
213
+ dfs = DFS.new(deepVal)
214
+ dfs.traverse(st.root)
215
+ expect(st.nodeFactory.valuePath(deepVal.deepestValueDepthNode)).to eq "in spite of his"
216
+ end
217
+
218
+ it "converts tree to suffix array" do
219
+ dataSource = StringDataSource.new "mississippi"
220
+ st = SuffixTree.new('$')
221
+ st.addDataSource dataSource
222
+
223
+ suffix_array = []
224
+ st.root.each_suffix do |suffixOffset|
225
+ suffix_array << suffixOffset
226
+ end
227
+ expect(suffix_array).to eq [11, 10, 7, 4, 1, 0, 9, 8, 6, 3, 5, 2]
228
+ end
229
+
230
+ describe "builds generalized suffix trees" do
231
+ let(:alphaDataSource) { StringDataSource.new "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqr" }
232
+ let(:alphaNodeFactory) { NodeFactory.new alphaDataSource }
233
+ let(:secondDataSource) { StringDataSource.new "asjdfkjaskdjfkajlxxxxxxxjklmnopqrstuvwxyzabcsdf;laksjdf aksjd"}
234
+
235
+ it "builds generalized suffix tree" do
236
+ st = SuffixTree.new('$', {:valueDepth => true})
237
+ st.addDataSource alphaDataSource
238
+ st.addDataSource secondDataSource
239
+
240
+ deepVal = DeepestValueDepthVisitor.new
241
+ dfs = DFS.new(deepVal)
242
+ dfs.traverse(st.root)
243
+ expect(st.nodeFactory.valuePath(deepVal.deepestValueDepthNode,'')).to eq "jklmnopqrstuvwxyzabc"
244
+ end
245
+
246
+ let(:src1) { StringDataSource.new "abcd" }
247
+ let(:src2) { StringDataSource.new "cxyz" }
248
+
249
+ it "uses multiple data sources" do
250
+ st = SuffixTree.new(nil, {:valueDepth => true, :dataSourceBit => true})
251
+ st.addDataSource src1
252
+ st.addDataSource src2
253
+
254
+ deepVal = DeepestValueDepthVisitor.new
255
+ dfs = DFS.new(deepVal)
256
+ dfs.traverse(st.root)
257
+ expect(st.nodeFactory.valuePath(deepVal.deepestValueDepthNode,'')).to eq "c"
258
+ dataSourceVisitor = DataSourceVisitor.new
259
+ dfs = DFS.new(dataSourceVisitor)
260
+ dfs.traverse(st.root)
261
+ expect(deepVal.deepestValueDepthNode.dataSourceBit).to eq 3
262
+ expect(st.root.dataSourceBit).to eq 3
263
+ expect(st.root.children['a'].dataSourceBit).to eq 1
264
+ expect(st.root.children['x'].dataSourceBit).to eq 2
265
+ expect(deepVal.deepestValueDepthNode.children['d'].dataSourceBit).to eq 1
266
+ expect(deepVal.deepestValueDepthNode.children['x'].dataSourceBit).to eq 2
267
+ end
268
+ end
269
+
270
+ end
data/spec/util_spec.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'rspec'
2
+ require_relative '../lib/visitor/numbering_visitor'
3
+
4
+
5
+ describe 'utility' do
6
+ it 'should find right-most 1-bit' do
7
+ bu = BitUtil.new
8
+ (0..63).each do |n|
9
+ expect(bu.rightBit(2**n)).to eq (n+1)
10
+ end
11
+ expect(bu.rightBit(65)).to eq (1)
12
+ expect(bu.rightBit(66)).to eq (2)
13
+ end
14
+
15
+ it 'should find left-most 1-bit' do
16
+ bu = BitUtil.new
17
+ (0..63).each do |n|
18
+ expect(bu.leftBit(2**n)).to eq (n+1)
19
+ end
20
+ expect(bu.leftBit(65)).to eq (7)
21
+ expect(bu.leftBit(66)).to eq (7)
22
+ expect(bu.leftBit(129)).to eq (8)
23
+ expect(bu.leftBit(280)).to eq (9)
24
+ end
25
+
26
+ it 'finds bit common to two values greater than or equal to a given value' do
27
+ bu = BitUtil.new
28
+ expect(bu.bitGreaterThanOrEqualTo(1, 1, 1)).to eq 1
29
+ expect(bu.bitGreaterThanOrEqualTo(1, 2, 2)).to eq 2
30
+ expect(bu.bitGreaterThanOrEqualTo(1, 3, 3)).to eq 1
31
+ expect(bu.bitGreaterThanOrEqualTo(1, 4, 4)).to eq 3
32
+ expect(bu.bitGreaterThanOrEqualTo(1, 8, 8)).to eq 4
33
+ expect(bu.bitGreaterThanOrEqualTo(1, 7, 6)).to eq 2
34
+ expect(bu.bitGreaterThanOrEqualTo(2, 5, 6)).to eq 3
35
+ expect(bu.bitGreaterThanOrEqualTo(10, 1024+2048, 2049)).to eq 12
36
+ end
37
+
38
+ it 'finds left most bit to right of a given bit' do
39
+ bu = BitUtil.new
40
+ expect(bu.leftMostBitToRightOf(2, 1)).to eq 1
41
+ expect(bu.leftMostBitToRightOf(4, 1)).to eq 1
42
+ expect(bu.leftMostBitToRightOf(8, 3)).to eq 2
43
+ expect(bu.leftMostBitToRightOf(8, 15)).to eq 4
44
+ expect(bu.leftMostBitToRightOf(8, 22)).to eq 5
45
+ expect(bu.leftMostBitToRightOf(8, 33)).to eq 6
46
+ end
47
+ end
@@ -0,0 +1,310 @@
1
+ require 'rspec'
2
+ require_relative '../lib/location'
3
+ require_relative '../lib/node'
4
+ require_relative '../lib/node_factory'
5
+ require_relative '../lib/data/string_data_source'
6
+ require_relative '../lib/data/file_data_source'
7
+ require_relative '../lib/suffix_tree'
8
+ require_relative '../lib/visitor/bfs'
9
+ require_relative '../lib/visitor/data_source_visitor'
10
+ require_relative '../lib/visitor/k_common_visitor'
11
+ require_relative '../lib/visitor/leaf_count_visitor'
12
+ require_relative '../lib/visitor/value_depth_visitor'
13
+ require_relative '../lib/visitor/dfs'
14
+ require_relative '../lib/visitor/node_count_visitor'
15
+ require_relative '../lib/visitor/suffix_offset_visitor'
16
+ require_relative '../lib/visitor/numbering_visitor'
17
+ require_relative '../lib/visitor/tree_print_visitor'
18
+
19
+ describe 'character depth visitor' do
20
+
21
+ let (:dataSource) { StringDataSource.new("mississippi") }
22
+ let (:stringNodeFactory) { NodeFactory.new dataSource }
23
+ let (:stringRootNodeId) { stringNodeFactory.nextNodeId }
24
+ let (:fileDataSource) { FileDataSource.new(File.join('spec', 'fixtures', "mississippi.txt")) }
25
+ let (:fileNodeFactory) { NodeFactory.new fileDataSource }
26
+
27
+ def verifyValueDepth(root)
28
+ expect(root.valueDepth).to eq (0)
29
+ mChild = root.children['m']
30
+ iChild = root.children['i']
31
+ sChild = root.children['s']
32
+ pChild = root.children['p']
33
+ expect(pChild.valueDepth).to eq (1)
34
+ expect(pChild.children['p'].valueDepth).to eq (Node::LEAF_DEPTH)
35
+ expect(pChild.children['i'].valueDepth).to eq (Node::LEAF_DEPTH)
36
+ expect(mChild.valueDepth).to eq (Node::LEAF_DEPTH)
37
+ expect(iChild.valueDepth).to eq (1)
38
+ expect(iChild.children['p'].valueDepth).to eq (Node::LEAF_DEPTH)
39
+ isChild = iChild.children['s']
40
+ expect(isChild.valueDepth).to eq (4)
41
+ expect(isChild.children['s'].valueDepth).to eq(Node::LEAF_DEPTH)
42
+ expect(isChild.children['p'].valueDepth).to eq(Node::LEAF_DEPTH)
43
+ expect(sChild.valueDepth).to eq (1)
44
+ siChild = sChild.children['i']
45
+ ssChild = sChild.children['s']
46
+ expect(siChild.valueDepth).to eq (2)
47
+ expect(ssChild.valueDepth).to eq (3)
48
+ expect(siChild.children['p'].valueDepth).to eq(Node::LEAF_DEPTH)
49
+ expect(siChild.children['s'].valueDepth).to eq(Node::LEAF_DEPTH)
50
+ expect(ssChild.children['s'].valueDepth).to eq(Node::LEAF_DEPTH)
51
+ expect(ssChild.children['p'].valueDepth).to eq(Node::LEAF_DEPTH)
52
+ end
53
+
54
+ context "DFS traversal" do
55
+ it "sets character depth using depth first traversal" do
56
+
57
+ hash = {
58
+ :valueDepth => true
59
+ }
60
+ st = SuffixTree.new(nil, hash)
61
+ st.addDataSource(dataSource)
62
+
63
+ cdv = DFS.new(ValueDepthVisitor.new)
64
+ cdv.traverse(st.root)
65
+ self.verifyValueDepth(st.root)
66
+ end
67
+ end
68
+
69
+ context "BFS traversal" do
70
+ it "sets character depth using breadth first traversal" do
71
+ st = SuffixTree.new(nil, { :valueDepth => true })
72
+ st.addDataSource(dataSource)
73
+ cdv = BFS.new(ValueDepthVisitor.new)
74
+ cdv.traverse(st.root)
75
+ self.verifyValueDepth(st.root)
76
+ end
77
+ end
78
+
79
+ def verifyLeafCount(root)
80
+ lcv = DFS.new(LeafCountVisitor.new)
81
+ lcv.traverse(root)
82
+ expect(root.leafCount).to eq (10) # final 'i' is implicit
83
+ mChild = root.children['m']
84
+ iChild = root.children['i']
85
+ sChild = root.children['s']
86
+ pChild = root.children['p']
87
+ expect(mChild.leafCount).to eq (1)
88
+ expect(iChild.leafCount).to eq (3)
89
+ expect(sChild.leafCount).to eq (4)
90
+ expect(pChild.leafCount).to eq (2)
91
+ end
92
+
93
+ context "DFS traversal" do
94
+ it "sets leaf count for suffix tree created from string" do
95
+ hash = {
96
+ :leafCount => true
97
+ }
98
+ st = SuffixTree.new(nil, hash)
99
+ st.addDataSource(dataSource)
100
+ self.verifyLeafCount(st.root)
101
+ end
102
+ end
103
+
104
+ context "DFS traversal" do
105
+ it "sets leaf count for suffix tree loaded from file" do
106
+ hash = {
107
+ :leafCount => true
108
+ }
109
+ st = SuffixTree.new(nil, hash)
110
+ st.addDataSource(fileDataSource)
111
+ self.verifyLeafCount(st.root)
112
+ end
113
+ end
114
+
115
+ def verifyNodeCount(dataSource)
116
+ st = SuffixTree.new(nil, nil)
117
+ st.addDataSource(fileDataSource)
118
+ ncv = NodeCountVisitor.new
119
+ bt = DFS.new(ncv)
120
+ bt.traverse(st.root)
121
+ expect(ncv.count).to eq (17)
122
+ bncv = NodeCountVisitor.new
123
+ bfst = BFS.new(bncv)
124
+ bfst.traverse(st.root)
125
+ expect(bncv.count).to eq (17)
126
+ end
127
+
128
+ context "Count nodes" do
129
+ it "counts nodes with DFS traversal of file data source" do
130
+ verifyNodeCount(fileDataSource)
131
+ end
132
+ end
133
+
134
+ context "Count nodes" do
135
+ it "counts nodes with DFS traversal of string data source" do
136
+ verifyNodeCount(dataSource)
137
+ end
138
+ end
139
+
140
+ context "collect suffix offsets" do
141
+ it "traverses suffix tree and collects suffix offsets" do
142
+ soCollector = SuffixOffsetVisitor.new
143
+ so = BFS.new(soCollector)
144
+ st = SuffixTree.new(nil, nil)
145
+ st.addDataSource(dataSource)
146
+ so.traverse(st.root)
147
+ expect(soCollector.result.sort).to eq ([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ])
148
+ end
149
+ end
150
+
151
+ describe "generalized suffix tree" do
152
+ let(:s1) { StringDataSource.new "sandollar" }
153
+ let(:s2) { StringDataSource.new "sandlot" }
154
+ let(:s3) { StringDataSource.new "handler" }
155
+ let(:s4) { StringDataSource.new "grand" }
156
+ let(:s5) { StringDataSource.new "pantry" }
157
+
158
+ it "KCommonVisitor finds longest substring common to k strings" do
159
+ # make the generalized suffix tree
160
+ st = SuffixTree.new("$", {:valueDepth => true, :dataSourceBit => true})
161
+ st.addDataSource(s1)
162
+ st.addDataSource(s2)
163
+ st.addDataSource(s3)
164
+ st.addDataSource(s4)
165
+ st.addDataSource(s5)
166
+
167
+ dataSourceVisitor = DataSourceVisitor.new
168
+ dfs = DFS.new(dataSourceVisitor)
169
+ dfs.traverse(st.root)
170
+ kCommonVisitor = KCommonVisitor.new(s1)
171
+ dfs = DFS.new(kCommonVisitor)
172
+ dfs.traverse(st.root)
173
+ longestLength,sample = kCommonVisitor.longestStringCommonTo(2)
174
+ expect(longestLength).to eq 4
175
+ expect(sample).to eq "sand"
176
+ longestLength,sample = kCommonVisitor.longestStringCommonTo(3)
177
+ expect(longestLength).to eq 3
178
+ expect(sample).to eq "and"
179
+ longestLength,sample = kCommonVisitor.longestStringCommonTo(4)
180
+ expect(longestLength).to eq 3
181
+ expect(sample).to eq "and"
182
+ longestLength,sample = kCommonVisitor.longestStringCommonTo(5)
183
+ expect(longestLength).to eq 2
184
+ expect(sample).to eq "an"
185
+ end
186
+ end
187
+
188
+ describe "DFS depth number" do
189
+ it "sets sets depth numbers and count of nodes in subtree for nodes" do
190
+ st = SuffixTree.new
191
+ st.addDataSource(dataSource)
192
+ dfs = OrderedDFS.new(NumberingVisitor.new)
193
+ dfs.traverse(st.root)
194
+ expect(st.root.dfsNumber).to eq 1
195
+ expect(st.root.numberNodesInSubtree).to eq 17
196
+
197
+ iChild = st.root.children['i']
198
+ expect(iChild.dfsNumber).to eq 2
199
+ expect(iChild.numberNodesInSubtree).to eq 5
200
+ expect(iChild.children['p'].dfsNumber).to eq 3
201
+ expect(iChild.children['p'].numberNodesInSubtree).to eq 1
202
+ expect(iChild.children['s'].dfsNumber).to eq 4
203
+ expect(iChild.children['s'].numberNodesInSubtree).to eq 3
204
+ expect(iChild.children['s'].children['p'].dfsNumber).to eq 5
205
+ expect(iChild.children['s'].children['p'].numberNodesInSubtree).to eq 1
206
+ expect(iChild.children['s'].children['s'].dfsNumber).to eq 6
207
+ expect(iChild.children['s'].children['s'].numberNodesInSubtree).to eq 1
208
+
209
+ mChild = st.root.children['m']
210
+ expect(mChild.dfsNumber).to eq 7
211
+ expect(mChild.numberNodesInSubtree).to eq 1
212
+
213
+ pChild = st.root.children['p']
214
+ expect(pChild.dfsNumber).to eq 8
215
+ expect(pChild.numberNodesInSubtree).to eq 3
216
+ expect(pChild.children['i'].dfsNumber).to eq 9
217
+ expect(pChild.children['p'].dfsNumber).to eq 10
218
+
219
+ sChild = st.root.children['s']
220
+ expect(sChild.dfsNumber).to eq 11
221
+ expect(sChild.numberNodesInSubtree).to eq 7
222
+ expect(sChild.children['i'].dfsNumber).to eq 12
223
+ expect(sChild.children['i'].numberNodesInSubtree).to eq 3
224
+ expect(sChild.children['i'].children['p'].dfsNumber).to eq 13
225
+ expect(sChild.children['i'].children['p'].numberNodesInSubtree).to eq 1
226
+ expect(sChild.children['i'].children['s'].dfsNumber).to eq 14
227
+ expect(sChild.children['i'].children['s'].numberNodesInSubtree).to eq 1
228
+ expect(sChild.children['s'].dfsNumber).to eq 15
229
+ expect(sChild.children['s'].numberNodesInSubtree).to eq 3
230
+ expect(sChild.children['s'].children['p'].dfsNumber).to eq 16
231
+ expect(sChild.children['s'].children['p'].numberNodesInSubtree).to eq 1
232
+ expect(sChild.children['s'].children['s'].dfsNumber).to eq 17
233
+ expect(sChild.children['s'].children['s'].numberNodesInSubtree).to eq 1
234
+ end
235
+ end
236
+
237
+ describe "DFS node path numbers number" do
238
+ it "sets sets node depth numbers then path numbers" do
239
+ st = SuffixTree.new
240
+ st.addDataSource(dataSource)
241
+ dfs = OrderedDFS.new(NumberingVisitor.new)
242
+ dfs.traverse(st.root)
243
+ dfs = OrderedDFS.new(RunDefiningVisitor.new)
244
+ dfs.traverse(st.root)
245
+ dfs = DFS.new(RunBitVisitor.new(st.root))
246
+ dfs.traverse(st.root)
247
+
248
+ expect(st.root.runTail.binaryTreeHeight).to eq 5
249
+ expect(st.root.runTail.dfsNumber).to eq 16
250
+ expect(st.root.runBits).to eq 16
251
+
252
+ iChild = st.root.children['i']
253
+ expect(iChild.runTail.binaryTreeHeight).to eq 3
254
+ expect(iChild.runTail.dfsNumber).to eq 4
255
+ expect(iChild.runBits).to eq 20 # 16 (binaryTreeHeight 5) + 4 (binaryTreeHeight 3)
256
+
257
+ expect(iChild.children['p'].runTail.binaryTreeHeight).to eq 1
258
+ expect(iChild.children['p'].runTail.dfsNumber).to eq 3
259
+ expect(iChild.children['p'].runBits).to eq 21
260
+ expect(iChild.children['s'].runTail.binaryTreeHeight).to eq 3
261
+ expect(iChild.children['s'].runTail.dfsNumber).to eq 4
262
+ expect(iChild.children['s'].runBits).to eq 20
263
+ expect(iChild.children['s'].children['p'].runTail.binaryTreeHeight).to eq 1
264
+ expect(iChild.children['s'].children['p'].runTail.dfsNumber).to eq 5
265
+ expect(iChild.children['s'].children['p'].runBits).to eq 21
266
+ expect(iChild.children['s'].children['s'].runTail.binaryTreeHeight).to eq 2
267
+ expect(iChild.children['s'].children['s'].runTail.dfsNumber).to eq 6
268
+ expect(iChild.children['s'].children['s'].runBits).to eq 22
269
+
270
+ mChild = st.root.children['m']
271
+ expect(mChild.runTail.binaryTreeHeight).to eq 1
272
+ expect(mChild.runTail.dfsNumber).to eq 7
273
+ expect(mChild.runBits).to eq 17
274
+
275
+ pChild = st.root.children['p']
276
+ expect(pChild.runTail.binaryTreeHeight).to eq 4
277
+ expect(pChild.runTail.dfsNumber).to eq 8
278
+ expect(pChild.runBits).to eq 24
279
+ expect(pChild.children['i'].runTail.binaryTreeHeight).to eq 1
280
+ expect(pChild.children['i'].runTail.dfsNumber).to eq 9
281
+ expect(pChild.children['i'].runBits).to eq 25
282
+ expect(pChild.children['p'].runTail.binaryTreeHeight).to eq 2
283
+ expect(pChild.children['p'].runTail.dfsNumber).to eq 10
284
+ expect(pChild.children['p'].runBits).to eq 26
285
+
286
+ sChild = st.root.children['s']
287
+ expect(sChild.runTail.binaryTreeHeight).to eq 5
288
+ expect(sChild.runTail.dfsNumber).to eq 16
289
+ expect(sChild.runBits).to eq 16
290
+ expect(sChild.children['i'].runTail.binaryTreeHeight).to eq 3
291
+ expect(sChild.children['i'].runTail.dfsNumber).to eq 12
292
+ expect(sChild.children['i'].runBits).to eq 20
293
+ expect(sChild.children['i'].children['p'].runTail.binaryTreeHeight).to eq 1
294
+ expect(sChild.children['i'].children['p'].runTail.dfsNumber).to eq 13
295
+ expect(sChild.children['i'].children['p'].runBits).to eq 21
296
+ expect(sChild.children['i'].children['s'].runTail.binaryTreeHeight).to eq 2
297
+ expect(sChild.children['i'].children['s'].runTail.dfsNumber).to eq 14
298
+ expect(sChild.children['i'].children['s'].runBits).to eq 22
299
+ expect(sChild.children['s'].runTail.binaryTreeHeight).to eq 5
300
+ expect(sChild.children['s'].runTail.dfsNumber).to eq 16
301
+ expect(sChild.children['s'].runBits).to eq 16
302
+ expect(sChild.children['s'].children['p'].runTail.binaryTreeHeight).to eq 5
303
+ expect(sChild.children['s'].children['p'].runTail.dfsNumber).to eq 16
304
+ expect(sChild.children['s'].children['p'].runBits).to eq 16
305
+ expect(sChild.children['s'].children['s'].runTail.binaryTreeHeight).to eq 1
306
+ expect(sChild.children['s'].children['s'].runTail.dfsNumber).to eq 17
307
+ expect(sChild.children['s'].children['s'].runBits).to eq 17
308
+ end
309
+ end
310
+ end