Skip to content

Commit 5940bbb

Browse files
authored
Merge pull request #329 from herobank110/master
Add Boyer Moore horspool algorithm (compile time evaluated)
2 parents 201e870 + aaaebae commit 5940bbb

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

Diff for: boyer_moore_horspool.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Compile Time Evaluated Boyer Moore Horspool String Search Algorithm
2+
// Author: David Kanekanian
3+
//
4+
// Requires C++17.
5+
6+
#include <string_view> // std::string_view
7+
#include <optional> // std::optional
8+
#include <array> // std::array
9+
#include <iostream> // std::cout
10+
11+
12+
struct SearchPattern {
13+
constexpr static std::size_t num_chars{ 256 };
14+
const std::string_view needle;
15+
std::array<char, num_chars> bad_char_table{};
16+
17+
constexpr SearchPattern(const std::string_view needle) noexcept
18+
: needle(needle) {
19+
// compute bad char table
20+
21+
// Rule 1
22+
// Characters not in the needle jump the length of the needle.
23+
for (std::size_t i = 0; i < num_chars; i++) {
24+
bad_char_table[i] = needle.length();
25+
}
26+
27+
// Rule 2
28+
// Characters in the needle except last character jump:
29+
// length of needle - last position of character - 1
30+
for (std::size_t i = 0; i < needle.length(); i++) {
31+
bad_char_table[needle[i]] = needle.length() - i - 1;
32+
}
33+
}
34+
};
35+
36+
/** Returns index of first occurrance of pattern in haystack. */
37+
[[nodiscard]] constexpr std::optional<std::size_t> boyer_moore_horspool (
38+
const SearchPattern& pattern,
39+
const std::string_view haystack) noexcept {
40+
for (std::size_t h = 0; h < haystack.length() - pattern.needle.length() + 1;) {
41+
// Search this placement of the needle.
42+
bool found = true;
43+
for (std::size_t n = pattern.needle.length() - 1; ; n--) {
44+
// Check the needle in reverse.
45+
if (haystack[h + n] != pattern.needle[n]) {
46+
// Bad character found.
47+
found = false;
48+
// Jump based on the bad character table.
49+
h += pattern.bad_char_table[haystack[h + n]];
50+
break;
51+
}
52+
if (n == 0) {
53+
break;
54+
}
55+
}
56+
if (found) {
57+
return h;
58+
}
59+
}
60+
61+
// Not found in the haystack.
62+
return std::nullopt;
63+
}
64+
65+
int main() {
66+
constexpr SearchPattern needle{ "abc" };
67+
constexpr auto haystack = "aa abc ddef";
68+
constexpr auto index = boyer_moore_horspool(needle, haystack);
69+
static_assert(index == 3, "index is supposed to be 3!");
70+
71+
if (index) {
72+
std::cout << "found at index " << index.value() << '\n';
73+
} else {
74+
std::cout << "not found" << '\n';
75+
}
76+
}

0 commit comments

Comments
 (0)