Proofs: SA-IS algorithm
These are the human proofs of SA-IS algorithm, at full length.
SA-IS returns the suffix array in linear time full
This proof shows: correctness, termination, complexity.
Let with and for , so the sentinel is the unique smallest symbol. Write . All suffixes are distinct, since they have distinct lengths and each contains the sentinel exactly once, at its end. The types are as defined on the page: is S-type, and for , is S-type if and L-type if .
Lemma 1 (type rule). For : if then is S-type; if then is L-type; if then has the type of .
Proof. The first two cases are decided by the first symbol. If , then and , so if and only if . For this case cannot happen, since is unique.
So the right-to-left scan of line L1 computes the types.
Lemma 2 (L before S in a bucket). If , is L-type and is S-type, then .
Proof. Let with the first symbol different from , . By Lemma 1 the type of is the type at the last of the run, which is L-type, so . In the same way with . If , position of the two suffixes has the symbol of there (it is if and if ). If , position has in and in . Either way .
So each bucket of consists of the L-type suffixes that start with , followed by the S-type suffixes that start with .
Lemma 3 (successor order). If and , then if and only if .
Proof. and with equal first symbols.
Lemma 4 (induced sorting of suffixes). Suppose is empty except that the LMS positions are placed at the ends of their buckets, and within each bucket in increasing order of their suffixes. Then INDUCE-L followed by INDUCE-S leaves the suffix array of in .
Proof. INDUCE-L. Every L-type has , and is either L-type or S-type; if it is S-type it is LMS, since its left neighbor is L-type. We show by induction on the rank of among the L-type suffixes that each L-type is written exactly once, at its final rank, and before the scan reaches that rank.
Take an L-type and assume the claim for all smaller L-type suffixes. Its successor is in at its final rank before the scan reaches that rank: an LMS position was placed there at the start, and an L-type successor is smaller, so the induction applies. The L-type suffixes in bucket that are smaller than have, by Lemma 3, smaller successors, so their successors are read before and they are written before ; the larger ones have larger successors and are written after . So when the scan reads , the head of bucket is exactly at the final rank of , by Lemma 2, and is written there. This rank is larger than the rank of , since , so the scan has not yet passed it and will read later. Each entry is read once, so is written once. The LMS entries are not moved, and empty slots are skipped.
INDUCE-S. The scan goes right to left with fresh tail pointers, so the LMS entries placed before are overwritten as the S-type positions are written. Every S-type has . By the symmetric induction, from the largest S-type suffix down: when the scan reads , which is either L-type (already in its final place after INDUCE-L) or S-type and larger (already written by this scan, at a rank to the right), is written at the tail of bucket . By Lemma 3, among S-type positions in one bucket the larger suffix has the larger successor, which is read earlier, so the S-part of each bucket is filled from its end in decreasing order. The sentinel is alone in bucket 0. Every S-type position has a successor that is read, so all S-type positions are written. With Lemma 2 this gives every bucket in sorted order, and the buckets are in order of their first symbols.
Lemma 5 (sorting the LMS substrings). After lines L3 to L5, the LMS positions appear in in an order in which their LMS substrings are nondecreasing, where LMS substrings are compared symbol by symbol, and at an equal symbol by type with L before S, up to and including the next LMS position.
Proof. Run the argument of Lemma 4 with each suffix replaced by its LMS prefix, the string of pairs (symbol, type) from to the first LMS position after , inclusive (for , just the sentinel). Lemmas 2 and 3 hold for LMS prefixes with this order: the type pair settles the case of Lemma 2, and for a non-LMS successor the LMS prefix of is followed by the LMS prefix of . At the start, the LMS positions are at the ends of their buckets in some order; their LMS prefixes are compared only at the first pair inside a bucket, which is (c, S) for all of them, so any order is consistent with the LMS prefixes truncated to one symbol. The induction then shows that every L-type and S-type non-LMS position is placed in the order of its LMS prefix, and in INDUCE-S the LMS positions themselves are rewritten, each induced from its successor, in the order of its LMS substring.
Lemma 6 (reduction). Let be the LMS positions and let be the name of the LMS substring at given by line L6. Then if and only if , where is the suffix of from .
Proof. By Lemma 5 and line L6, names are equal exactly for equal LMS substrings (as strings of pairs), and a smaller name means a smaller LMS substring. is the name of the sentinel substring, which is the smallest and unique, so again ends with a unique smallest symbol. Compare and : read their LMS substrings one after another. While the names agree, the substrings are equal, including the type of the last symbol, so the two suffixes continue from LMS positions and . At the first where the names differ, the LMS substrings differ. If they differ at a symbol, that symbol decides both comparisons in the same way. If they first differ in type at some offset with equal symbols, then the suffix with the L-type position is smaller there by the argument of Lemma 2 (applied to the two positions, which have the same symbol), and the L type is also smaller in the pair order. One LMS substring cannot be a proper prefix of the other as a string of pairs: if the shorter one ends at the LMS position , then is S-type and is L-type, and the other substring has the same pairs at the same offsets, so its position at that offset is also LMS and it ends there too. So the first difference of names gives the order of the suffixes, which is also the order of and .
Theorem. SA-IS returns the suffix array of .
Proof. By strong induction on the length of . If all names are distinct (line L8), the order of the names is the order of the LMS substrings, which by Lemma 6 with distinct names is the order of the LMS suffixes. Otherwise, has length for (no two LMS positions are adjacent, and 0 is never LMS), its alphabet is , and it ends with a unique smallest 0; by induction line L7 returns its suffix array, and by Lemma 6 this is the order of the LMS suffixes. Lines L9 and L10 then satisfy the hypothesis of Lemma 4, which gives the suffix array. For there is at most one LMS position and the names are distinct.
Termination and time. Each call on a string of length with alphabet size does work outside the recursion: the type scan, four bucket computations, four induction scans and the placement loops are each linear. In the naming, the comparison of two neighboring LMS substrings runs over at most the length of the shorter one plus one; each position lies in at most two LMS substrings (its own and as the shared end of the previous one), and each substring is compared at most twice (with its left and right neighbor in ), so the naming is . The recursive call is on symbols with alphabet size at most . So , and with at the top and below, . The length at least halves at each level and the recursion stops when the names are distinct, which happens at length 1 at the latest, so the depth is at most and the algorithm terminates.