diff --git a/strings/z_function.cpp b/strings/z_function.cpp new file mode 100644 index 000000000..960edc6a1 --- /dev/null +++ b/strings/z_function.cpp @@ -0,0 +1,75 @@ +/** + * @file + * @brief The Z function 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 + * 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] + * LINK + * https://cp-algorithms.com/string/z-function.html + * @author [Ritika Gupta](https://github.com/RitikaGupta8734) + */ + +#include +#ifdef _MSC_VER +#include // use this for MS Visual C++ +#else +#include +#endif +#include +# include + +/** + * Generate the Z-function for the inputted string. + * \param[in] pattern text on which to apply the Z-function + * \returns the Z-function output as a vector array + */ +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; + } + return z; +} + +/** + * 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 + */ +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 matching_indexes; + + for (int i = 0; i < text_length; i++) { + if(z[i+pattern_length+1]==pattern_length) matching_indexes.push_back(i); + } + return matching_indexes; +} + + +/** Main function */ +int main() { + 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::string text2 = "greengrass"; + std::string pattern2 = "abc"; + + std::vector matching_indexes2=find_pat_in_text(pattern2,text2); + assert((matching_indexes2 == std::vector{})); + + return 0; +}