Proofs: Ukkonen's algorithm
These are the human proofs of Ukkonen's algorithm, at full length.
Ukkonen's algorithm keeps the implicit suffix tree and runs in linear time full
This proof shows: correctness, termination, complexity.
Let with and not in . For let . The implicit suffix tree is the compact trie of the suffixes of : the trie of these strings with every node removed that has one child and is neither the root nor the end of a string that is not a proper prefix of another one. A suffix of is open if it is not a proper prefix of another substring of that extends it, that is, if it occurs in only as a suffix; open suffixes are exactly those that end at leaves.
Lemma 1 (suffix closure). If a string occurs in , every suffix of occurs in . If a suffix of is not open (it occurs earlier too), then every shorter suffix of is not open. Proof. The first is clear. For the second, occurs at some position other than the end, followed by a symbol; a suffix of occurs at the corresponding place, followed by the same symbol.
So the suffixes of split into open ones, the longest, and non-open ones, the shortest, including the empty suffix. Let be the number of non-open nonempty suffixes; they are .
Lemma 2 (once a leaf, always a leaf). An open suffix of becomes , an open suffix of . Proof. If occurred elsewhere in , then would occur in followed by a symbol.
Lemma 3 (suffix links exist). In , if labels an inner node other than the root, then labels an inner node or the root. Proof. is followed in by two distinct symbols, and so is .
Invariant. At the start of phase (line L3): (U1) the tree with open leaf edges ending at is , and each leaf is labeled with the start of its suffix; (U2) ; (U3) the active point is the place of (the root if ), and when , is the string from to the active point; (U4) every inner node other than the root has a suffix link to the node of its label without the first symbol.
Initially , the tree is the root, , and all of (U1) to (U4) hold.
One phase. Let . Line L3 increases to , counting the new empty-plus- suffix: the strings to be extended by without a leaf are for , and line L4 handles them from the longest. The open suffixes are extended by through their open leaf edges, without work, and stay open by Lemma 2.
Consider a pass with , the active point at the place of (by (U3), adjusted below). Lines L5 and L8 bring the active point to a canonical form, where is less than the length of the edge it is on; line L8 is correct without reading symbols because, by (U3), is spelled from the root, so the edge into matches the next symbols of .
- If follows the place of (line L9), then occurs in , so it is not open in , and by Lemma 1 none of is open either; all of them are spelled in the tree by Lemma 1. Nothing is added. The non-open suffixes of are , so (U2), and moves the active point to the place of (U3).
- Otherwise does not occur in , so it is a new open suffix of , and it needs a leaf. If the place is a node, line L7 adds the leaf; if it is inside an edge, line L10 splits the edge at that place with a new node , whose label is now followed by and by the old next symbol, so is a valid branching node, and adds the leaf. In both cases the trie stays compact. The leaf is for the suffix that starts at .
After line L11, , and the next string to handle is , which is without its first symbol. If is the root, its place is found by dropping the first symbol of the string from the root, which line L12 does (the new string starts at and has length ). Otherwise is an inner node whose label is a prefix of , and by (U4) its link is the node of ; the active point then spells followed by the same symbols, which is . If was the root and , then was empty () and the loop ends.
If the loop ends because , then all of became leaves, every suffix of is open except the empty one, , and the active point is the root.
Suffix links (U4). A node created in line L10 for is an inner node of with label , . If , its link is the root, which line L12 then reaches: the next pass is at the root and either adds a leaf at the root (line L7, which sets root) or stops by rule 3 at the root (line L9, same). If , the next pass handles , the label of without its first symbol: it either finds a node there (rule 3 at a node, or rule 2 at a node, line L7), or creates one by a split (line L10); in each case it sets to that node, which is the node of , as Lemma 3 requires. The pass handles the place of exactly, so it cannot be a different node. So at the end of the phase every new inner node has its link, except possibly the last one, whose next pass must exist: the last node is created at (at the active point is the root, is empty, and line L7 runs, not line L10), so one more pass follows in the same phase.
End. After phase , with the sentinel, no nonempty suffix of occurs twice, since each ends with the only . So , all nonempty suffixes are open and end at leaves, and is the suffix tree of .
Time. Each pass of the inner loop either breaks (once per phase, at most times) or creates a leaf. Leaves are never removed (Lemma 2), and there are at most of them, so there are at most passes. Define the node depth as the number of nodes on the path from the root to , the root excluded. For an inner node with label , each ancestor root of has label with a prefix of , and its link, the node of , is an ancestor of the node of or the root, distinct for distinct (the labels differ), except that the ancestor with label links to the root. So . Line L13 lowers the active node depth by at most 1, line L12 does not change , a split changes no node depth of the active node, and each step of line L8 raises it by 1. The node depth is at most at all times, starts at 0, and drops by at most in each of the at most passes, so the number of steps of line L8 is at most . Each step takes time with constant-time child lookup. So the total time is , and the algorithm terminates.