Skip to content

Commit 149878b

Browse files
authored
Merge pull request #5 from sandyre/algorithm-dev
KMP algorithm
2 parents 93ef41f + 460bbf7 commit 149878b

File tree

4 files changed

+107
-1
lines changed

4 files changed

+107
-1
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#ifndef CSLIB_ALGORITHM_SEARCH_KMP_SEARCH_HPP
2+
#define CSLIB_ALGORITHM_SEARCH_KMP_SEARCH_HPP
3+
4+
// MIT License
5+
//
6+
// Copyright (c) 2018 Alexandr Borzykh
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// of this software and associated documentation files (the "Software"), to deal
10+
// in the Software without restriction, including without limitation the rights
11+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the Software is
13+
// furnished to do so, subject to the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included in all
16+
// copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
// SOFTWARE.
25+
26+
#include <cslib/data_structure/dynamic_array.hpp>
27+
28+
#include <iterator>
29+
30+
namespace cslib {
31+
namespace algorithm
32+
{
33+
34+
/* Name: Knuth-Morris-Pratt searching algorithm
35+
* Runtime complexity: O(n)
36+
* Space complexity: O(m), where m is pattern
37+
*
38+
* Interesting fact: it's widely used with strings, but implementation is generic and can work with basically all containers and types (contained type must have operator==)
39+
*/
40+
41+
template < typename IteratorT >
42+
IteratorT kmp_search(IteratorT begin, IteratorT end, IteratorT pattern_begin, IteratorT pattern_end)
43+
{
44+
using iterator_traits = std::iterator_traits<IteratorT>;
45+
46+
const typename iterator_traits::difference_type source_length = std::distance(begin, end), pattern_length = std::distance(pattern_begin, pattern_end);
47+
data_structure::dynamic_array<uint32_t> prefix_func(pattern_length, 0);
48+
49+
uint32_t k;
50+
IteratorT pattern_iter;
51+
for (k = 0, pattern_iter = pattern_begin; pattern_iter != pattern_end; ++pattern_iter)
52+
{
53+
while ((k > 0) && (*pattern_iter != *(pattern_begin + k)))
54+
k = prefix_func[k - 1];
55+
56+
if (*pattern_iter == *(pattern_begin + k))
57+
++k;
58+
59+
prefix_func[std::distance(pattern_begin, pattern_iter)] = k;
60+
}
61+
62+
IteratorT source_iter;
63+
for (k = 0, source_iter = begin; source_iter != end; ++source_iter)
64+
{
65+
while ((k > 0) && (*(pattern_begin + k) != *source_iter))
66+
k = prefix_func[k - 1];
67+
68+
if (*(pattern_begin + k) == *source_iter)
69+
++k;
70+
71+
if (k == pattern_length)
72+
return source_iter - pattern_length + 1;
73+
}
74+
75+
return end;
76+
}
77+
78+
}}
79+
80+
#endif

include/cslib/data_structure/dynamic_array.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ namespace data_structure
144144
: _data(std::allocator_traits<allocator>::allocate(_allocator, initial_size)),
145145
_capacity(initial_size),
146146
_size(initial_size)
147-
{ algorithm::for_each_iterator(begin(), end(), std::bind(&std::allocator_traits<allocator>::construct, std::ref(_allocator), std::placeholders::_1, filler)); }
147+
{ algorithm::for_each_iterator(begin(), end(), [&](pointer ptr) { std::allocator_traits<allocator>::construct(_allocator, ptr, filler); }); }
148148

149149

150150
template < typename ValueT >

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ option(BUILD_TESTS "Build unit tests" OFF)
33
SET(SOURCES
44
algorithm/binary_search.cpp
55
algorithm/linear_search.cpp
6+
algorithm/kmp_search.cpp
67

78
algorithm/insertion_sort.cpp
89
algorithm/maximum_subarray.cpp

tests/algorithm/kmp_search.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <cslib/algorithm/search/kmp_search.hpp>
4+
5+
#include <vector>
6+
7+
template <typename T>
8+
using DefaultContainer = std::vector<T>;
9+
10+
TEST(kmp_search, empty_input)
11+
{
12+
DefaultContainer<int> container;
13+
DefaultContainer<int> pattern { 5 };
14+
15+
ASSERT_EQ(cslib::algorithm::kmp_search(container.begin(), container.end(), pattern.begin(), pattern.end()), container.end());
16+
}
17+
18+
19+
TEST(kmp_search, simple_input)
20+
{
21+
DefaultContainer<int> container { 0, 10, 5, 4, 3 };
22+
DefaultContainer<int> pattern { 5, 4, 3 };
23+
24+
ASSERT_EQ(cslib::algorithm::kmp_search(container.begin(), container.end(), pattern.begin(), pattern.end()), container.begin() + 2);
25+
}

0 commit comments

Comments
 (0)