Skip to content

Commit b82e2cd

Browse files
RitikaGupta8734Panquesito7github-actions
authored
feat: added z_algorithm in strings (#1581)
* feat: added z_algorithm in strings * Updated z_function.cpp Updated z_function.cpp as per contribution guidelines. Fixed Link using github markdown syntax Created a separate function for tests and covered the corner case * Apply suggestions from code review More comments added to the code Co-authored-by: David Leal <[email protected]> * Apply suggestions from code review Some more documentation added as per contribution guidelines. Co-authored-by: David Leal <[email protected]> * Update strings/z_function.cpp comments added Co-authored-by: David Leal <[email protected]> * Update strings/z_function.cpp Co-authored-by: David Leal <[email protected]> * updating DIRECTORY.md * clang-format and clang-tidy fixes for 0c7515e * Updated int -> uint64_t Updated int -> uint64_t for non-negative values * clang-format and clang-tidy fixes for 12d5123 * Update strings/z_function.cpp Co-authored-by: David Leal <[email protected]> * Update strings/z_function.cpp Co-authored-by: David Leal <[email protected]> * More comments added * clang-format and clang-tidy fixes for 8a627ac * Update strings/z_function.cpp Co-authored-by: David Leal <[email protected]> * Update strings/z_function.cpp Co-authored-by: David Leal <[email protected]> Co-authored-by: David Leal <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent 341ed50 commit b82e2cd

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

DIRECTORY.md

+1
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,4 @@
334334
* [Knuth Morris Pratt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/knuth_morris_pratt.cpp)
335335
* [Manacher Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/manacher_algorithm.cpp)
336336
* [Rabin Karp](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/rabin_karp.cpp)
337+
* [Z Function](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/z_function.cpp)

strings/z_function.cpp

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* @file
3+
* @brief The [Z function](https://cp-algorithms.com/string/z-function.html) for
4+
* finding occurences of a pattern within a piece of text with time and space
5+
* complexity O(n + m)
6+
* @details
7+
* 1. The Z-function for a string is an array of length n where the
8+
* i-th element is equal to the greatest number of characters starting
9+
* from the position i that coincide with the first characters of s.
10+
* 2. E.g.: string: ababb then z[2]=2 as s[2]=s[0] and s[3]=s[1] and s[4]!=s[2]
11+
* @author [Ritika Gupta](https://github.com/RitikaGupta8734)
12+
*/
13+
14+
#include <iostream> /// for IO operations
15+
#ifdef _MSC_VER
16+
#include <string> /// for string (use this for MS Visual C++)
17+
#else
18+
#include <cstring> /// for string
19+
#endif
20+
#include <cassert> /// for assert
21+
#include <vector> /// for std::vector
22+
23+
/**
24+
* @brief Generate the Z-function for the inputted string.
25+
* \param[in] pattern text on which to apply the Z-function
26+
* \returns the Z-function output as a vector array
27+
*/
28+
std::vector<uint64_t> Z_function(const std::string &pattern) {
29+
uint64_t pattern_length = pattern.size();
30+
std::vector<uint64_t> z(pattern_length, 0);
31+
32+
for (uint64_t i = 1, l = 0, r = 0; i < pattern_length; i++) {
33+
if (i <= r) {
34+
z[i] = std::min(r - i + 1, z[i - l]);
35+
}
36+
while (i + z[i] < pattern_length &&
37+
pattern[z[i]] == pattern[i + z[i]]) {
38+
z[i]++;
39+
}
40+
if (i + z[i] - 1 > r) {
41+
r = i + z[i] - 1;
42+
}
43+
}
44+
return z;
45+
}
46+
47+
/**
48+
* @brief Using Z_function to find a pattern in a text
49+
* \param[in] pattern string pattern to search
50+
* \param[in] text text in which to search
51+
* \returns a vector of starting indexes where pattern is found in the text
52+
*/
53+
std::vector<uint64_t> find_pat_in_text(const std::string &pattern,
54+
const std::string &text) {
55+
uint64_t text_length = text.size(), pattern_length = pattern.size();
56+
std::vector<uint64_t> z = Z_function(pattern + '#' + text);
57+
std::vector<uint64_t> matching_indexes;
58+
59+
for (uint64_t i = 0; i < text_length; i++) {
60+
if (z[i + pattern_length + 1] == pattern_length) {
61+
matching_indexes.push_back(i);
62+
}
63+
}
64+
return matching_indexes;
65+
}
66+
67+
/**
68+
* @brief Self-test implementations
69+
* @returns void
70+
*/
71+
static void test() {
72+
// usual case
73+
std::string text1 = "alskfjaldsabc1abc1abcbksbcdnsdabcabc";
74+
std::string pattern1 = "abc";
75+
76+
// matching_indexes1 gets the indexes where pattern1 exists in text1
77+
std::vector<uint64_t> matching_indexes1 = find_pat_in_text(pattern1, text1);
78+
assert((matching_indexes1 == std::vector<uint64_t>{10, 14, 18, 30, 33}));
79+
80+
// corner case
81+
std::string text2 = "greengrass";
82+
std::string pattern2 = "abc";
83+
84+
// matching_indexes2 gets the indexes where pattern2 exists in text2
85+
std::vector<uint64_t> matching_indexes2 = find_pat_in_text(pattern2, text2);
86+
assert((matching_indexes2 == std::vector<uint64_t>{}));
87+
}
88+
89+
/**
90+
* @brief Main function
91+
* @returns 0 on exit
92+
*/
93+
int main() {
94+
test(); // run self-test implementations
95+
return 0;
96+
}

0 commit comments

Comments
 (0)