Lecture 1 (Strings hard problems)¶
Z function¶
Given two strings, one is a text string and the other is a pattern string. Print the indexes of all occurrences of the pattern string in the text string using the Z function algorithm. Use 0-based indexing while returning the indices.
Input: text = "xyzabxyzabxyz", pattern = "xyz"
Output: [0, 5, 10]
Input: text = "cabcdab", pattern = "abc"
Output: [1]
Approach 1 (Brute Force)¶
- Build match function (that takes start idx)
- Call match function every idx
In [3]:
def z_function(text,pattern):
T = len(text)
P = len(pattern)
def match(start):
i =0
while start < T and i < P and text[start]== pattern[i]:
i+=1
start +=1
return i == P
result = []
for i in range(T):
if match(i):
result.append(i)
return result
print(z_function("xyzabxyzabxyz","xyz"))
print(z_function("cabcdab","abc"))
[0, 5, 10] [1]
Complexity¶
- T = len(text) and P = len(pattern)
- O(T * P)
- O(1)
Approach 2 (Z function)¶
- Build the z array
- Z[i] = len(substring) starting from index i that match prefix of string
- zbox : left ,right
- STEP 1: Use previous computations if inside the Z-box
- STEP 2: Extend the match as far as possible
- STEP 3: Update Z-box if we've extended beyond it Refer https://www.youtube.com/watch?v=CpZh4eF8QBw
In [ ]:
def compute_z(s):
n = len(s)
z = [0] *n
left ,right = 0,0
for i in range(1,n):
# STEP 1: Use previous computations if inside the Z-box
if i <= right:
z[i] = min(z[i - left], right - i + 1)
# STEP 2: Extend the match as far as possible
while i + z[i] <n and s[z[i]] == s[i + z[i]]:
z[i] +=1
# STEP 3: Update Z-box if we've extended beyond it
if i + z[i] -1 > right:
left = i
right = i+ z[i] -1
return z
def z_function(text,pattern):
combined = pattern + "#" + text
z = compute_z(combined)
result = []
for i in range(len(combined)):
if z[i] == len(pattern):
result.append(i - len(pattern)-1)
return result
print(z_function("xyzabxyzabxyz","xyz"))
print(z_function("cabcdab","abc"))
[0, 5, 10] [1]
Complexity¶
- T = len(text) and P = len(pattern)
- O(T + P)
- O (T +P)