|
| 1 | +/*For the sake of brevity, let's call segment matches those substrings that coincide with a prefix of s. For example, the value of the desired Z-function z[i] is the length of the segment match starting at position i (and that ends at position i+z[i]−1). |
| 2 | +To do this, we will keep the [l,r] indices of the rightmost segment match. That is, among all detected segments we will keep the one that ends rightmost. In a way, the index r can be seen as the "boundary" to which our string s has been scanned by the algorithm; everything beyond that point is not yet known. |
| 3 | +Then, if the current index (for which we have to compute the next value of the Z-function) is i, we have one of two options: |
| 4 | +i>r -- the current position is outside of what we have already processed. |
| 5 | +We will then compute z[i] with the trivial algorithm (that is, just comparing values one by one). Note that in the end, if z[i]>0, we'll have to update the indices of the rightmost segment, because it's guaranteed that the new r=i+z[i]−1 is better than the previous r. |
| 6 | +i≤r -- the current position is inside the current segment match [l,r]. |
| 7 | +Then we can use the already calculated Z-values to "initialize" the value of z[i] to something (it sure is better than "starting from zero"), maybe even some big number. |
| 8 | +For this, we observe that the substrings s[l…r] and s[0…r−l] match. This means that as an initial approximation for z[i] we can take the value already computed for the corresponding segment s[0…r−l], and that is z[i−l]. |
| 9 | +However, the value z[i−l] could be too large: when applied to position i it could exceed the index r. This is not allowed because we know nothing about the characters to the right of r: they may differ from those required. |
| 10 | +*/ |
| 11 | + |
| 12 | + |
| 13 | +#include <bits/stdc++.h> |
| 14 | +using namespace std; |
| 15 | +//fuction to calculate z array/vector. |
| 16 | +//O(N+m) N,m are length of text and patterns respectively. |
| 17 | +vector<int> Z_array(string s) |
| 18 | +{ |
| 19 | + |
| 20 | + int n = s.size(); |
| 21 | + vector<int> z_array(n); |
| 22 | + int ss = 0, es = 0; |
| 23 | + // ss== start segment es== end segment |
| 24 | + //(ss and es is range of current segment which is prevoiusly occured/found.) |
| 25 | + for (int i = 1; i < n; ++i) |
| 26 | + { |
| 27 | + if (i <= es) |
| 28 | + z_array[i] = min(es - i + 1, z_array[i - ss]); |
| 29 | + while (i + z_array[i] < n && s[z_array[i]] == s[i + z_array[i]]) |
| 30 | + //for maching characters we have to increase our range of segment and update the z_array |
| 31 | + z_array[i]++; |
| 32 | + if (i + z_array[i] - 1 > es) |
| 33 | + //if we have already processed then we have to use prevoius value |
| 34 | + //for maintaining the condition l<=i<=r<=n ; |
| 35 | + ss = i, es = i + z_array[i] - 1; |
| 36 | + } |
| 37 | + return z_array; |
| 38 | +} |
| 39 | + |
| 40 | +int main() |
| 41 | +{ |
| 42 | + string text, pat; |
| 43 | + cin >> text >> pat; |
| 44 | + string total = pat + "@" + text; |
| 45 | + vector<int> output = Z_array(total); |
| 46 | + for (int i = 0; i < output.size(); i++) |
| 47 | + { |
| 48 | + if (output[i] == pat.size()) |
| 49 | + //To obtain the actual position of pattern in a given string. |
| 50 | + //we have to subtract the pattern length +1(1 for special character) |
| 51 | + cout << (i - pat.length() - 1) << " "; |
| 52 | + |
| 53 | + } |
| 54 | + |
| 55 | + return 0; |
| 56 | +} |
0 commit comments