Worked examples — Suffix array — construction O(n log n), LCP array
3.8.7 · D3· Coding › String Algorithms › Suffix array — construction O(n log n), LCP array
Yeh parent Suffix-Array note ka hands-on companion hai. Parent ne machinery banai thi; yahan hum us machinery ko har tarah ke input par chalate hain jo ek problem tumhe de sakti hai — including woh weird degenerate cases jo naive code ko tod dete hain.
Scenario matrix
Har string jo tum kabhi bhi suffix array mein daaloge, woh in cells mein se kisi ek mein aati hai. Last column us example ka naam batata hai jo ise pin karta hai.
| Cell | Scenario class | Kya break ho sakta hai | Example |
|---|---|---|---|
| A | Generic mixed string | prefix-doubling rounds, sentinel | Ex 1 (mississippi) |
| B | Sab characters equal (aaaa) |
har suffix ek prefix share karta hai; LCP ek staircase hai | Ex 2 |
| C | Sab characters distinct (abcd) |
pehla round already finish ho jaata hai; LCP sab zero | Ex 3 |
| D | Length 1 (a) |
ek suffix, koi adjacent pair nahi, koi LCP entry nahi | Ex 4 |
| E | Empty string () | loops nahi chalane chahiye; array empty hai | Ex 4 |
| F | Kasai "drop by at most 1" reuse | galat reset karna → | Ex 5 |
| G | Word problem — pattern search | binary-search block contiguous hona chahiye | Ex 6 |
| H | LCP se distinct substrings count karna | do sums mein off-by-one | Ex 7 |
| I | Exam twist — do suffixes ka LCP via RMQ | non-adjacent pair ka LCP range-min chahta hai | Ex 8 |
Cells A–I sab neeche cover hain. Chalte hain inhe walk karte hue.
Ex 1 — Cell A: ek generic string, full doubling
Ex 2 — Cell B: sab characters equal
Ex 3 — Cell C: sab characters distinct
Ex 4 — Cells D & E: length 1 aur empty (degenerate)
Ex 5 — Cell F: Kasai ka "drop by at most 1" reuse dekhna
, par chalao, aur dekho Forecast: Do consecutive -steps ke beech mein, kitna gir sakta hai? Maximum guess karo.
Pehle humein chahiye. Suffixes: 0 aab, 1 ab, 2 b. Sorted: aab < ab < b.
Step 1 — , rank : koi predecessor nahi.
Kyun? Suffix aab sorted order mein pehla hai. Set karo , . Phir .
Step 2 — , rank : predecessor .
Kyun? Compare karo aur . Match karo a (pos 0), phir b vs a mismatch → . Set karo . Phir .
Step 3 — , rank : predecessor .
Kyun? Compare karo aur . Pehla char b vs a mismatch → . Set karo .
Reuse in action: se Step 3 se pehle carried tak ki drop exactly 1 thi — kabhi zyada nahi. Woh guaranteed cap hi reason hai ki total work hai: har character index ko sirf bounded number of times "re-scan" kiya ja sakta hai.
reset karna Yahan (chhoti string mein) yeh phir bhi sahi LCP dega, lekin long shared prefixes wali strings par yeh baar baar scratch se re-scan karta hai → . ko carry karo.
Verify: , aur distinct substrings : a, aa, aab, ab, b. ✅
Ex 6 — Cell G: word problem, pattern search
"banana" mein "an" kitni baar aata hai?
Forecast: Sab matches suffix array ka ek contiguous block mein hote hain. Guess karo woh block kitna bada hai.
Parent se: banana ke liye, yaani sorted suffixes
r=0 SA=5 a
r=1 SA=3 ana
r=2 SA=1 anana
r=3 SA=0 banana
r=4 SA=4 na
r=5 SA=2 nana
Step 1 — ek match = ek suffix jiska prefix "an" hai.
Yeh step kyun? mein pattern ki har occurrence ek suffix hai jo se start hoti hai. Kyunki suffixes sorted hain, woh ek contiguous run banate hain — binary-searchable.
Step 2 — prefix "an" ka lower aur upper bound binary search karo.
Yeh step kyun? Hum pehla sorted suffix "an" chahte hain aur pehla "an\xff" (kuch bhi "an…" block se thoda aage).
- Lower bound:
"ana"at (yeh"an"hai). - Upper bound:
"banana"at pehla hai jo"an"se start nahi hota. - Toh block hai .
Step 3 — occurrences padhna.
Block size . Starting positions aur .
banana → b a n a n a; positions 1 (anana) aur 3 (banana). 2 occurrences.
Verify: banana ko haath se scan karo, an index 1 aur index 3 par aata hai. Count . ✅
Ex 7 — Cell H: distinct substrings count karna (formula drill)
ke distinct substrings,
Forecast: abab clearly bahut zyada repeat karta hai. Kya distinct count 10 (sab) ke kareeb hoga ya 6 ke?
Step 1 — banao. Suffixes: 0 abab, 1 bab, 2 ab, 3 b. Sorted: ab < abab < b < bab.
Step 2 — LCP banao.
- :
abvsababshareab→ . - :
ababvsbkuch share nahi karte → . - :
bvsbabshareb→ .
Step 3 — counting formula apply karo. Yeh formula kyun? sab substrings count karta hai (har suffix apne length-many prefixes contribute karta hai). unhe remove karta hai jo twice count hue kyunki adjacent suffixes ne ek prefix share kiya tha.
Verify: list karo — a, ab, aba, abab, b, ba, bab = 7. ✅ (10 se zyada 6 ke kareeb — repetition distinctness khaata hai.)
Ex 8 — Cell I: exam twist, do non-adjacent suffixes ka LCP
"banana" mein aur ka Longest common prefix
Forecast: Woh mein neighbors NAHI hain. Toh LCP array akele direct answer nahi deta. Value guess karo, phir trick dekho.
Yaad karo , , .
Step 1 — dono suffixes ko sorted order mein locate karo. Yeh step kyun? Kisi bhi do suffixes ka LCP unke beech sorted-order stretch par minimum LCP ke barabar hota hai. Toh pehle unke ranks dhundho.
- (suffix
banana). - (suffix
nana).
Step 2 — LCP ka range minimum lo. Yeh step kyun? Sorted order mein rank 3 se rank 5 tak chalte hue, har adjacent pair sirf utna share karta hai jitna uska LCP hai; endpoints ka shared prefix us raaste ke sabse chhote LCP se lamba nahi ho sakta. Yeh ek range-minimum query hai → Sparse Table use karo. (Hum LCP indices of larger par lete hain, yaani aur .)
Step 3 — interpret karo.
LCP : banana (b se shuru) aur nana (n se shuru) koi prefix share nahi karte.
Verify: banana vs nana — pehle chars b ≠ n. Common prefix length . ✅
Recall RMQ kyun, fresh scan kyun nahi?
Ek fresh character-by-character compare per query hai. LCP array plus RMQ ke saath mein precompute karke, har "LCP of two suffixes" query ho jaati hai. Yahi LCP array ka poora payoff hai.
Recap
Recall Har example ne kaun sa cell cover kiya?
Ex 1 ::: A — generic string, full prefix-doubling Ex 2 ::: B — sab equal characters (staircase LCP) Ex 3 ::: C — sab distinct (ek round, zero LCP) Ex 4 ::: D aur E — length 1 aur empty string Ex 5 ::: F — Kasai ka carry-over, drop-by-1 Ex 6 ::: G — pattern search via contiguous block Ex 7 ::: H — distinct-substring counting formula Ex 8 ::: I — non-adjacent suffixes ka LCP via RMQ
"E-D-B-C-F" — Empty, length-one (D), all-equal (B, longest→last), all-distinct (C, ek round), aur Kasai ka carried F (kabhi reset mat karo).
Related tools jo revisit karne layak hain: Radix Sort aur Counting Sort (fast per-round sorting), Suffix Tree (bhaari cousin), Z-Algorithm aur KMP (single-pattern alternatives), aur Burrows–Wheeler Transform (sorted-suffix order se directly banta hai).