diff --git a/strings/z_function.cpp b/strings/z_function.cpp index e0941a73d..6056dd5ae 100644 --- a/strings/z_function.cpp +++ b/strings/z_function.cpp @@ -1,24 +1,25 @@ /** * @file - * @brief The [Z function](https://cp-algorithms.com/string/z-function.html) for finding occurences of a pattern - * within a piece of text with time and space complexity O(n + m) - * @details + * @brief The [Z function](https://cp-algorithms.com/string/z-function.html) for + * finding occurences of a pattern within a piece of text with time and space + * complexity O(n + m) + * @details * DESCRIPTION - * 1. The Z-function for a string is an array of length n where the - * i-th element is equal to the greatest number of characters starting + * 1. The Z-function for a string is an array of length n where the + * i-th element is equal to the greatest number of characters starting * from the position i that coincide with the first characters of s. * 2. Eg string : ababb then z[2]=2 as s[2]=s[0] and s[3]=s[1] and s[4]!=s[2] * @author [Ritika Gupta](https://github.com/RitikaGupta8734) */ -#include /// for IO operations +#include /// for IO operations #ifdef _MSC_VER #include /// for string (use this for MS Visual C++) #else -#include /// for string +#include /// for string #endif -#include /// for std::vector -#include /// for assert +#include /// for assert +#include /// for std::vector /** * @brief Generate the Z-function for the inputted string. @@ -27,12 +28,15 @@ */ std::vector Z_function(const std::string &pattern) { int pattern_length = pattern.size(); - std::vector z(pattern_length,0); - - for (int i = 1,l = 0,r = 0; i < pattern_length; i++) { - if(i<=r)z[i]=std::min(r-i+1,z[i-l]); - while(i+z[i]r)r=i+z[i]-1; + std::vector z(pattern_length, 0); + + for (int i = 1, l = 0, r = 0; i < pattern_length; i++) { + if (i <= r) + z[i] = std::min(r - i + 1, z[i - l]); + while (i + z[i] < pattern_length && pattern[z[i]] == pattern[i + z[i]]) + z[i]++; + if (i + z[i] - 1 > r) + r = i + z[i] - 1; } return z; } @@ -41,36 +45,38 @@ std::vector Z_function(const std::string &pattern) { * @brief Using Z_function to find a pattern in a text * \param[in] pattern string pattern to search * \param[in] text text in which to search - * \returns a vector of starting indexes where pattern is found in the text + * \returns a vector of starting indexes where pattern is found in the text */ -std::vector find_pat_in_text(const std::string &pattern, const std::string &text) { +std::vector find_pat_in_text(const std::string &pattern, + const std::string &text) { int text_length = text.size(), pattern_length = pattern.size(); - std::vector z = Z_function(pattern+'#'+text); + std::vector z = Z_function(pattern + '#' + text); std::vector matching_indexes; for (int i = 0; i < text_length; i++) { - if(z[i+pattern_length+1]==pattern_length) matching_indexes.push_back(i); + if (z[i + pattern_length + 1] == pattern_length) + matching_indexes.push_back(i); } return matching_indexes; -} +} /** * @brief Self-test implementations * @returns void */ -static void test(){ +static void test() { // usual case std::string text1 = "alskfjaldsabc1abc1abcbksbcdnsdabcabc"; std::string pattern1 = "abc"; - - std::vector matching_indexes1=find_pat_in_text(pattern1,text1); - assert((matching_indexes1 == std::vector{10,14,18,30,33})); - + + std::vector matching_indexes1 = find_pat_in_text(pattern1, text1); + assert((matching_indexes1 == std::vector{10, 14, 18, 30, 33})); + // corner case std::string text2 = "greengrass"; std::string pattern2 = "abc"; - - std::vector matching_indexes2=find_pat_in_text(pattern2,text2); + + std::vector matching_indexes2 = find_pat_in_text(pattern2, text2); assert((matching_indexes2 == std::vector{})); } @@ -79,7 +85,6 @@ static void test(){ * @returns 0 on exit */ int main() { - test(); // run self-test implementations return 0; }