What
Calculate the array z where z[i] = longest common prefix of s and s[i:].
Idea

- use dynamic programming
- maintain the interval
[l, r]where:s[l : r + 1] == s[:r - l + 1](s[l...r]is a prefix ofs)ris as big as possible
- for each position
i, use the interval[l, r]to initializez[i]:- if
l <= i <= rthens[l : i] == s[:i - l + 1]- because
s[l : r + 1] == s[:r - l + 1](defined above)
- because
- if
i > rthen keep as0
- if
- then try increase
z[i](expand the prefix starts ati) using the naive approach. - update
[l, r]with[i, i + z[i] - 1]ifi + z[i] - 1 > r- this keeps
i > land increaseras newz[i]is computed.
- this keeps
Implementation
def zfunction(s):
n = len(s)
z = [0] * n
# maintain the interval [l, r], where
# s[l : r + 1] == s[:r - l + 1] and `r` is max
l, r = 0, 0
# start from 1 because z[0] = n and will make `r` becomes `n - 1`
# i will always be > l
for i in range(1, n):
# initialize z[i] based on info from the interval [l, r]
# because s[l : r + 1] == s[:r - l + 1]
# thus s[l : i] == s[:i - l + 1] for l <= i <= r
if i <= r:
z[i] = min(z[i - l], r - i + 1)
# trying to extend the match
while i + z[i] < n and s[z[i]] == s[i + z[i]]:
z[i] += 1
# update the interval [l, r]
if r < i + z[i] - 1:
l, r = i, i + z[i] - 1
return zComplexity
- Time:
ris always increase at each iteration
- Space:
Misc
- This has a similar spirit to LSP - Longest Suffix which is also a prefix.
- Reference: Z-function - VNOI wiki