We maintain a window [l,r] = rightmost segment matching the prefix found so far (start l=r=0).
For each i from 1 to n−1, two cases:
Case A — i>r (we're outside any known box).
We have no information. Compare from scratch:
Z[i]=max{k:s[k]=s[i+k]}
starting at k=0. If Z[i]>0, set the new box l=i,r=i+Z[i]−1.
Case B — i≤r (we're inside the box).
Let i′=i−l be the mirror position in the prefix. We know Z[i′]. Two sub-cases:
B1: Z[i′]<r−i+1. The mirror's match fits entirely inside the box. Since inside the box s equals the prefix exactly, the match at i is identical:
Z[i]=Z[i′](no comparisons, no box update)Why no comparison? Because the mismatch that ended the mirror's match is still inside the box, so it's guaranteed to repeat at i.
B2: Z[i′]≥r−i+1. The mirror's match reaches the box boundary; beyond r we have no guarantee, so we must compare manually starting from k=r−i+1:
Z[i]=(r−i+1)+(extra matches found by comparing s[k] vs s[i+k])
Then update box to l=i,r=i+Z[i]−1.
To find pattern p (length m) in text t (length n): build string
S=p+#+t(#∈/p,t)
Compute Z over S (length m+1+n). Wherever Z[i]=m, the pattern occurs in t at position i−(m+1). Total cost O(n+m).
Imagine the first few letters of a word are your "secret code". You walk along the rest of the word asking at each spot: "Starting here, how many letters match the start of the word?" The slow way is to re-check from zero each time. The clever trick: if you already matched a long chunk earlier, that chunk is a photocopy of the beginning — so a spot inside it must behave the same as the matching spot near the start. You just look up the answer you already wrote down, instead of re-counting. You only do new counting when you walk past the edge of the photocopied chunk — and since that edge only ever moves forward, you never do too much work.
The length of the longest substring starting at index i that is also a prefix of s.
Why is naive Z computation O(n²)?
For strings like "aaa...a" each starting index re-scans to the end, summing to O(n²) comparisons.
What is the Z-box [l,r]?
The rightmost (largest r) interval already known to match the prefix: s[l..r] = s[0..r-l].
In Case B (i ≤ r), what is the mirror index?
i' = i - l; the corresponding position inside the prefix.
Why can we copy Z[i-l] inside the box without comparing?
Inside [l,r] the string equals the prefix, so s[i]=s[i-l]; the mirror's match (and its terminating mismatch) repeat exactly — if it stays within the box. :::
What does min(r-i+1, Z[i-l]) protect against?
Claiming matches beyond r that were never verified; it caps trust at the box boundary.
When do you update the box?
Only when i + Z[i] - 1 > r, i.e. the new match extends further right than the current box.
Why is the total cost O(n)?
Each inner while-iteration increases r by 1; r only grows and is ≤ n-1, so total extensions ≤ n.
How to do pattern matching with Z?
Build S = pattern + '#' + text, compute Z; positions where Z[i]=m (pattern length) are matches.
Why must the separator '#' be absent from both strings?
Otherwise a Z-match could span the boundary and report a false occurrence.
Dekho, Z-algorithm ka kaam simple hai: har index i ke liye batao ki wahan se shuru karke kitne characters string ke prefix se match karte hain. Yeh value Z[i] kehlati hai. Agar tum naive tarike se har position pe zero se compare karoge to worst case (jaise "aaaa...") mein O(n2) ho jata hai — bahut slow.
Trick yeh hai: jab tumne pehle se koi lamba match dhoond liya, to ek "Z-box" [l,r] banta hai jo prove karta hai ki s[l..r] bilkul prefix jaisa hai — yaani uska photocopy. Ab agar tumhe kisi i ka Z chahiye jo is box ke andar hai, to box ke andar ka character s[i] exactly s[i−l] ke barabar hai. Iska matlab Z[i-l] (mirror position) ka answer tum free mein copy kar sakte ho — koi comparison nahi! Sirf jab tum box ke right edge r se aage nikalte ho, tab actual comparison karte ho.
Aur yahi linear time ka raaz hai: har baar jab tum aage compare karte ho aur match milta hai, r ek aage badh jata hai. r kabhi peeche nahi jata aur n se zyada nahi ho sakta — isliye total extra comparisons sirf n tak. Bas yaad rakho: min(r-i+1, Z[i-l]) lagana zaroori hai, warna tum box ke bahar wale unverified matches claim kar baithoge.
Pattern matching ke liye to bilkul mast use hota hai: S=pattern+#+text banao, Z nikaalo, aur jahan Z[i]=m (pattern length) wahan match mil gaya — sab O(n+m) mein. Competitive programming mein yeh ek must-know weapon hai.