Skip to content

Commit cacfbac

Browse files
committed
docs: explain the non-obvious steps in suffix array
1 parent 8be06b2 commit cacfbac

1 file changed

Lines changed: 11 additions & 0 deletions

File tree

‎strings/suffix_array.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,22 @@ def suffix_array(text: str) -> list[int]:
3838
return []
3939

4040
suffixes = list(range(n))
41+
# Ranking by code point is enough to start: Python orders strings by code
42+
# point too, so one comparison of the first character is already right.
4143
rank = list(map(ord, text))
4244
k = 1
4345

4446
while k < n:
47+
# Sort by the first 2k characters of each suffix, which are exactly the
48+
# pair (rank of the first k, rank of the next k). A second half that
49+
# runs past the end gets -1: ranks are never negative, so a shorter
50+
# suffix sorts before a longer one that shares its prefix.
4551
keys = [(rank[i], rank[i + k] if i + k < n else -1, i) for i in range(n)]
4652
keys.sort()
4753
suffixes = [i for _, _, i in keys]
4854

55+
# Renumber so that equal 2k-prefixes share a rank and every distinct
56+
# prefix gets the next one. This keeps ranks dense in range(n).
4957
new_rank = [0] * n
5058
for position in range(1, n):
5159
previous, current = suffixes[position - 1], suffixes[position]
@@ -60,6 +68,9 @@ def suffix_array(text: str) -> list[int]:
6068
new_rank[current] = new_rank[previous] + int(previous_key != current_key)
6169

6270
rank = new_rank
71+
# Dense ranks ending at n - 1 means every suffix has a unique rank, so
72+
# the 2k-prefixes already order them completely; doubling cannot change
73+
# the order, and the next round always breaks too, since 2k >= n.
6374
if rank[suffixes[-1]] == n - 1:
6475
break
6576
k *= 2

0 commit comments

Comments
 (0)