Proofs: Farach's algorithm
These are the human proofs of Farach's algorithm, at full length.
Farach's algorithm computes the suffix array and the LCP array in linear time full
This proof shows: correctness, termination, time.worst.
Notation. with symbols in at positions to and , the sentinel. Positions are 0-based, , and the order is lexicographic. Since the sentinel is unique and smallest, two different suffixes are never prefixes of each other: for , with , both and are less than and . We write for . A position is odd or even by its 0-based value. The proof is by induction on ; for , line L1 is direct.
Lemma 1 (odd suffixes). After L4, lists the odd positions in suffix order, and .
Proof. Let be the number of odd positions, and for let , with as a pad. The pair contains at its first or second place, and no other pair contains a 0, since for . Line L2 sets to the rank of , so if and only if , and is unique. Read two symbols at a time, is , followed by the pad. Two such sequences for differ at some pair before either ends, because the unique pair can only be matched by itself, at the same offset from the end, which would mean . So comparing them pair by pair is comparing the suffixes of at and with the extra 0 of L3 never reached, and it is also comparing and , since pairs compare as their two symbols. By induction ( for ), is the suffix array of , whose rank 0 is the suffix at index ; dropping it and mapping to gives .
For the LCP, let and , which are the suffixes of at ranks and of , so is the number of equal leading pairs, and by the argument above the first pair that differs comes no later than in either sequence. So and are the starts of the first pairs that differ, both less than . If , the lcp is . Otherwise the second symbols differ, and the lcp is .
Lemma 2 (even suffixes). After L6, lists the even positions in suffix order, and .
Proof. For an even , with odd and less than . So for two such positions, if and only if , or and , that is, the rank of in is smaller (Lemma 1). If is even, its suffix is the sentinel alone, the smallest suffix, and its key is the smallest key. So sorting by the key of L5 sorts the even suffixes. For two adjacent even suffixes and : if , their lcp is 0; otherwise both symbols are nonzero, since the sentinel is unique, and , which is the minimum of over the ranks after the smaller rank up to the larger rank by the LCP-RMQ lemma.
The trees and . and are the compacted tries of the odd and the even suffixes; with distinct suffixes and no suffix a prefix of another, each suffix is a leaf. A point of a tree is a node or a place inside an edge; it spells a string, its path. The overmerge (L12 to L15) builds from pairs of points: the root of is paired with the two roots. At a node of paired with the points and (either may be missing), the edges out of and are grouped by first symbol. For each symbol , a child of depth is made, where is the smaller depth of the targets of the edges with symbol (of one or both trees), and is paired with the points at depth on these edges. A leaf of a tree whose depth is makes a leaf of for that suffix. Let and be the paths of the points paired with . By induction from the root:
- (a) the depth of in is and , for each point that exists;
- (b) the odd leaves below in (with itself if it is an odd leaf) are exactly the odd leaves below the point of in , and in the same way for the even leaves;
- (c) the children of have different first symbols , and is the true symbol at offset of every suffix below that child;
- (d) every node of is paired with some node of , and so is every node of .
Point (d) holds because is never larger than the depth of either target, so the walk along an edge stops at its lower end. Each node of other than the root is at the lower end of an edge of one of the trees, so it is paired with a node of that tree, and each node of a tree is paired with only one node of , since the walk goes down. So has at most nodes, and the walk ends.
Lemma 3 (same parity). For two odd positions , . The same holds for two even positions.
Proof. Let be the LCA of and in ; its string depth is . By (d), is paired with a node of , and by (b) both leaves are below . In , the two leaves are in different subtrees of , whose edges have different first symbols, so by (c) they go to different children of , or one of them is . Hence is their LCA in , and by (a) its depth is .
Lemma 4 (different parity). For a node of with both points, let , at most . For an odd and an even with , . Moreover if and only if is the root.
Proof. By (b), starts with and with . If , the two paths differ at offset , so the suffixes do too, and . If , the suffixes share symbols. Neither of them can be itself as a leaf: a leaf suffix ends with the sentinel at offset , and the other suffix would hold the same sentinel at the same offset, so it would be the same suffix. So they go to different children of , whose first symbols differ by (c), and . At the root, both paths are empty and . At any other node, the first symbol of the path is the first symbol of the child of the root that holds , which is a true symbol of both paths by (c), so .
Lemma 5 (d-links). Lines L16 to L18 return for and of different parity.
Proof. Let . If is the root, the answer 0 is right by Lemma 4. Otherwise , so , both symbols are nonzero, and are positions of different parity, and . Each step of the loop goes to a pair one position further, so it ends at the root after at most steps, or earlier at a stored value. By induction along the chain from its end, each value computed is of its pair, and by Lemma 4 that value is for the node where it is stored. So a stored value is right for every later pair with the same LCA.
Theorem 1 (correctness). FARACH returns the suffix array and the LCP array of .
Proof. By Lemmas 3 and 5, for any two positions. With , if and only if . So L9 merges two lists that are sorted by Lemmas 1 and 2 with a correct comparison, and the result lists all suffixes in order. L10 is correct by the same two lemmas. The recursion ends, since its input is shorter.
Theorem 2 (time). On an integer alphabet with , with radix sort and linear-time range minimum and LCA structures, FARACH takes time in the worst case.
Proof. Without the recursive call: L2 is a radix sort of pairs with passes; L4 is a scan; L5 is a stable counting sort by of the even positions taken in the order of ; L6 is range minimum queries after linear preprocessing; L7 is two stack scans; L8 is the overmerge, work for each node of when the children of each point are grouped by first symbol with one global radix sort of all edges, and then linear LCA preprocessing. In L9 and L10 there are LCP queries. Each query of a different parity costs plus one loop step for each node whose value is stored for the first time, and each node of is stored at most once, so the total is . The recursive call is on symbols, with names at most . So , which gives , since the sizes form a geometric series.