19
19
20
20
namespace boost { namespace algorithm {
21
21
22
+ namespace detail {
23
+
22
24
/* *
23
- * One class, two identities.
25
+ * @brief Accelerated Linear search.
26
+ *
27
+ * Accelerated Linear (AL) search by Musser & Nishanov.
28
+ *
24
29
*/
25
- template <typename PatIter, typename CorpusIter = PatIter, typename Trait = search_trait<typename std::iterator_traits<PatIter>::value_type>, typename Enable = void >
26
- class musser_nishanov ;
27
-
28
30
template <typename PatIter, typename CorpusIter = PatIter, typename Trait = search_trait<typename std::iterator_traits<PatIter>::value_type> >
29
31
class accelerated_linear
30
32
{
31
33
BOOST_STATIC_ASSERT (( boost::is_same<
32
34
typename std::iterator_traits<PatIter>::value_type,
33
35
typename std::iterator_traits<CorpusIter>::value_type>::value ));
34
-
36
+ public:
35
37
typedef typename std::iterator_traits<PatIter>::difference_type pattern_difference_type;
36
38
typedef typename std::iterator_traits<CorpusIter>::difference_type corpus_difference_type;
37
39
40
+ protected:
38
41
PatIter pat_first, pat_last;
39
42
std::vector<corpus_difference_type> next_;
40
43
pattern_difference_type k_pattern_length;
41
-
44
+
45
+ private:
42
46
void compute_next ()
43
47
{
44
48
pattern_difference_type j = 0 , t = -1 ;
@@ -55,7 +59,7 @@ class accelerated_linear
55
59
}
56
60
57
61
public:
58
- std::pair<CorpusIter, CorpusIter> AL (CorpusIter corpus_first, CorpusIter corpus_last) const
62
+ std::pair<CorpusIter, CorpusIter> operator () (CorpusIter corpus_first, CorpusIter corpus_last) const
59
63
{
60
64
using std::find;
61
65
using std::make_pair;
@@ -131,6 +135,15 @@ class accelerated_linear
131
135
132
136
};
133
137
138
+ } // namespace detail
139
+
140
+
141
+ /* *
142
+ * One class, two identities based on corpus iterator and the suffix size trait.
143
+ */
144
+ template <typename PatIter, typename CorpusIter = PatIter, typename Trait = search_trait<typename std::iterator_traits<PatIter>::value_type>, typename Enable = void >
145
+ class musser_nishanov ;
146
+
134
147
135
148
/* *
136
149
* Musser-Nishanov Accelerated Linear search algorithm.
@@ -142,20 +155,12 @@ typename disable_if<
142
155
boost::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<CorpusIter>::iterator_category>,
143
156
boost::mpl::bool_<Trait::suffix_size>
144
157
>::type
145
- >::type> : private accelerated_linear<PatIter, CorpusIter, Trait>
158
+ >::type> : public boost::algorithm::detail:: accelerated_linear<PatIter, CorpusIter, Trait>
146
159
{
147
- using accelerated_linear<PatIter, CorpusIter, Trait>::AL;
160
+ typedef boost::algorithm::detail::accelerated_linear<PatIter, CorpusIter, Trait> AcceleratedLinear;
161
+
148
162
public:
149
- musser_nishanov (PatIter pat_first, PatIter pat_last) : accelerated_linear<PatIter, CorpusIter, Trait>(pat_first, pat_last) {}
150
-
151
- /* *
152
- * Run the search object on a corpus with forward or bidirectional iterators.
153
- */
154
- std::pair<CorpusIter, CorpusIter>
155
- operator ()(CorpusIter corpus_first, CorpusIter corpus_last) const
156
- {
157
- return AL (corpus_first, corpus_last);
158
- }
163
+ musser_nishanov (PatIter pat_first, PatIter pat_last) : AcceleratedLinear(pat_first, pat_last) {}
159
164
};
160
165
161
166
@@ -169,19 +174,18 @@ typename enable_if<
169
174
boost::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<CorpusIter>::iterator_category>,
170
175
boost::mpl::bool_<Trait::suffix_size>
171
176
>::type
172
- >::type>
177
+ >::type> : public boost::algorithm::detail::accelerated_linear<PatIter, CorpusIter, Trait>
173
178
{
174
- BOOST_STATIC_ASSERT (( boost::is_same<
175
- typename std::iterator_traits<PatIter>::value_type,
176
- typename std::iterator_traits<CorpusIter>::value_type>::value ));
179
+ typedef boost::algorithm::detail::accelerated_linear<PatIter, CorpusIter, Trait> AcceleratedLinear;
177
180
178
- typedef typename std::iterator_traits<PatIter>::difference_type pattern_difference_type;
179
- typedef typename std::iterator_traits<CorpusIter>::difference_type corpus_difference_type;
181
+ using typename AcceleratedLinear::pattern_difference_type;
182
+ using typename AcceleratedLinear::corpus_difference_type;
183
+ using AcceleratedLinear::k_pattern_length;
184
+ using AcceleratedLinear::pat_first;
185
+ using AcceleratedLinear::pat_last;
186
+ using AcceleratedLinear::next_;
180
187
181
- PatIter pat_first, pat_last;
182
- std::vector<corpus_difference_type> next_;
183
188
boost::array<corpus_difference_type, Trait::hash_range_max> skip;
184
- pattern_difference_type k_pattern_length;
185
189
corpus_difference_type mismatch_shift;
186
190
boost::function<std::pair<CorpusIter, CorpusIter>(CorpusIter, CorpusIter)> search;
187
191
@@ -206,7 +210,6 @@ typename enable_if<
206
210
if (k >= 0 ) break ;
207
211
do // this loop is hot for data read
208
212
{
209
- // unsigned char const index = Trait::hash(corpus_last + k);
210
213
corpus_difference_type const increment = skip[Trait::hash (corpus_last + k)];
211
214
k += increment;
212
215
}
@@ -262,27 +265,7 @@ typename enable_if<
262
265
return make_pair (corpus_last, corpus_last);
263
266
}
264
267
265
- std::pair<CorpusIter, CorpusIter> AL (CorpusIter corpus_first, CorpusIter corpus_last)
266
- {
267
- throw std::runtime_error (" Not implemented!" );
268
- return std::make_pair (corpus_first, corpus_last);
269
- }
270
268
271
- void compute_next ()
272
- {
273
- pattern_difference_type j = 0 , t = -1 ;
274
- next_.reserve (k_pattern_length);
275
- next_.push_back (-1 );
276
- while (j < k_pattern_length - 1 )
277
- {
278
- while (t >= 0 && pat_first[j] != pat_first[t])
279
- t = next_[t];
280
- ++j;
281
- ++t;
282
- next_.push_back (pat_first[j] == pat_first[t] ? next_[t] : t);
283
- }
284
- }
285
-
286
269
void compute_skip ()
287
270
{
288
271
pattern_difference_type const m = next_.size ();
@@ -294,13 +277,12 @@ typename enable_if<
294
277
}
295
278
296
279
public:
297
- musser_nishanov (PatIter pat_first, PatIter pat_last) : pat_first (pat_first) , pat_last(pat_last), k_pattern_length(std::distance(pat_first, pat_last) )
280
+ musser_nishanov (PatIter pat_first, PatIter pat_last) : AcceleratedLinear (pat_first, pat_last)
298
281
{
299
282
if (k_pattern_length > 0 )
300
283
{
301
- compute_next ();
302
284
if (k_pattern_length < Trait::suffix_size)
303
- search = bind (&musser_nishanov::AL , this , _1, _2);
285
+ search = bind (&AcceleratedLinear::operator () , this , _1, _2);
304
286
else
305
287
{
306
288
search = bind (&musser_nishanov::HAL, this , _1, _2);
@@ -317,6 +299,7 @@ typename enable_if<
317
299
}
318
300
};
319
301
302
+
320
303
template <typename PatIter, typename CorpusIter>
321
304
std::pair<CorpusIter, CorpusIter> musser_nishanov_search (CorpusIter corpus_first, CorpusIter corpus_last, PatIter pat_first, PatIter pat_last)
322
305
{
0 commit comments