Skip to content

Commit 60050d7

Browse files
Added Horspool algorithm (#1071)
* feat: add Horspool algorithm * Fixed conversion from unsigned long to int with static casting * Removed changes from CMakeLists.txt file * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Documentation, test function and namespaces added * Documentation, test function and namespaces added * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Update strings/horspool.cpp Co-authored-by: David Leal <[email protected]> * Removed blank rows * Commit to see if the problem with automated tests is solved Co-authored-by: David Leal <[email protected]>
1 parent 6e77f98 commit 60050d7

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

strings/horspool.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* @file
3+
* @brief Horspool's algorithm that finds if a string contains a substring (https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm)
4+
* @author [Harry Kontakis](https://github.com/ckontakis)
5+
*/
6+
7+
#include <iostream>
8+
#include <unordered_map>
9+
#include <cassert>
10+
11+
/**
12+
* @namespace strings
13+
* @brief Algorithms with strings
14+
*/
15+
namespace strings {
16+
/**
17+
* @namespace horspool
18+
* @brief Functions for [Horspool's](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm) algorithm
19+
*/
20+
namespace horspool {
21+
/**
22+
* A function that finds the shift table of the given prototype string that we need in Horpool's algorithm.
23+
* @param prototype is the substring that we use to find shift table
24+
* @return Shift Table of Horspool's algorithm
25+
*/
26+
std::unordered_map<char, int> findShiftTable(const std::string &prototype) {
27+
std::unordered_map<char, int>
28+
shiftTable; // A HashMap for shift table that has characters for keys and integers for values
29+
30+
for (int i = 0; i < prototype.size();
31+
i++) { // Checking all characters of prototype string
32+
if (shiftTable.find(prototype[i]) ==
33+
shiftTable.end()) { // If character does not exist in HashMap
34+
if (i != prototype.size() - 1) {
35+
shiftTable.insert(std::make_pair(
36+
prototype[i], prototype.size() - i -
37+
1)); // Insert the character as key and the size of prototype string - index of character - 1 as value
38+
} else {
39+
shiftTable.insert(std::make_pair(
40+
prototype[i],
41+
prototype.size())); // Insert the character as key and the size of prototype string as value
42+
}
43+
} else {
44+
if (i != prototype.size() - 1) {
45+
shiftTable[prototype[i]] = prototype.size() - i - 1;
46+
}
47+
}
48+
}
49+
return shiftTable;
50+
}
51+
52+
/**
53+
* A function that implements Horspool's algorithm.
54+
* @param text is the string that we are searching if there is a substring
55+
* @param prototype is the substring that we are searching in text
56+
* @returns true if text string contains prototype string
57+
* @returns false if text string does not contain prototype string
58+
*/
59+
bool horspool(const std::string &text, const std::string &prototype) {
60+
std::unordered_map<char, int> shiftTable = findShiftTable(
61+
prototype); // Initialise shift table calling findShiftTable function
62+
63+
int i = static_cast<int>(
64+
prototype.size() -
65+
1); // Index that we shift in text to find the substring
66+
while (i < text.size()) {
67+
int j = i, k = 0;
68+
bool flag = true;
69+
70+
for (int z = static_cast<int>(prototype.size() - 1); z >= 0 && flag;
71+
z--) { // Checking if all characters of substring are equal with all characters of string
72+
if (text[j] == prototype[z]) {
73+
k++;
74+
j--;
75+
} else {
76+
flag = false; // If two characters are not equal set flag to false and break from loop
77+
}
78+
}
79+
80+
if (k ==
81+
prototype.size()) { // If all characters match then return true
82+
return true;
83+
} else {
84+
if (shiftTable.find(text[i]) != shiftTable.end()) {
85+
i += shiftTable[text[i]]; // If shift table contains the character then shift index as many steps as value
86+
} else {
87+
i += prototype.size(); // If character does not exist in shift table then shift index as many steps as size of prototype string
88+
}
89+
}
90+
}
91+
return false;
92+
}
93+
} // namespace horspool
94+
} // namespace strings
95+
96+
/**
97+
* @brief Function with test cases for Horspool's algorithm
98+
* @returns void
99+
*/
100+
static void test(){
101+
assert(strings::horspool::horspool("Hello World","World") == true);
102+
assert(strings::horspool::horspool("Hello World"," World") == true);
103+
assert(strings::horspool::horspool("Hello World","ello") == true);
104+
assert(strings::horspool::horspool("Hello World","rld") == true);
105+
assert(strings::horspool::horspool("Hello","Helo") == false);
106+
assert(strings::horspool::horspool("c++_algorithms","c++_algorithms") == true);
107+
assert(strings::horspool::horspool("c++_algorithms","c++_") == true);
108+
assert(strings::horspool::horspool("Hello","Hello World") == false);
109+
assert(strings::horspool::horspool("c++_algorithms","") == false);
110+
assert(strings::horspool::horspool("c++","c") == true);
111+
assert(strings::horspool::horspool("3458934793","4793") == true);
112+
assert(strings::horspool::horspool("3458934793","123") == false);
113+
}
114+
115+
/**
116+
* @brief Main Function that calls test function
117+
* @returns 0 on exit
118+
*/
119+
int main(){
120+
test();
121+
return 0;
122+
}

0 commit comments

Comments
 (0)