Skip to content

Commit 2e82477

Browse files
authored
Merge pull request #263 from nirmalkatiyar/master
Added Z function
2 parents c1ab7cb + a0027f2 commit 2e82477

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include<bits/stdc++.h>
2+
using namespace std;
3+
//naive approach for finding Z function array(i.e. z[i] is the length of the longest string that is, at the same time, a prefix of s and a prefix of the suffix of s starting at i.)
4+
// i-th element is equal to the greatest number of characters starting from the position i that coincide with the first characters of s.
5+
//O(n^2)
6+
vector<int>Z_function(string s){
7+
int n = s.size();
8+
//vector z store the z values
9+
//i.e.(i-th element is equal to the greatest number of characters starting from the position i that coincide with the first characters of s)
10+
vector<int> z(n,0);
11+
//Traversing the whole string
12+
for (int i = 1; i < n; ++i)
13+
//comparing the characters and incresing the range i.e. length of substring which previously exists
14+
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
15+
++z[i];
16+
return z;
17+
}
18+
19+
int main(){
20+
string text;
21+
string pat;
22+
cin>>text>>pat;
23+
//making a temporary string total
24+
string total=pat+"$"+text;
25+
vector<int>OutputIndices=Z_function(total);
26+
//Z_function will return the array/vector of indices ie
27+
//i-th element is equal to the greatest number of characters starting from the position i that coincide with the first characters of temporary string total.
28+
//if size of pattern matches with any value of vector returned by z_function it means our pattern found in temporary string
29+
// but to get real index of pattern in given text we have to substract pattern length and 1 (for special character) from the index of vector returned by Z_function.
30+
for(auto i=0;i<OutputIndices.size();i++){
31+
if(OutputIndices[i]==pat.size()){
32+
33+
cout<<(i-pat.size()-1)<<" ";
34+
}
35+
}
36+
37+
38+
return 0;
39+
}

0 commit comments

Comments
 (0)