Proofs: Suffix trie
These are the human proofs of Suffix trie, at full length.
The suffix trie holds exactly the substrings, with their counts and ends full
This proof shows: correctness.
Let , and write . For a node , is the string spelled by the path from the root to . Edges out of a node carry distinct symbols, because line L5 creates a child for only when none exists. So for each string there is at most one node with .
Lemma (build). For , after the passes of line L2:
- the strings , over all nodes , are exactly the distinct prefixes of , together with ;
- for each node , ;
- for each node , is the list, in increasing order, of the with .
Proof. By induction on . For , line L1 makes only the root, , and the claims hold.
Step from to . The pass starts at the root (line L3). We show by induction on that before the iteration of line L4, is the node of . This holds for . In the iteration , line L5 makes sure that a child for exists, creating it if the string had no node, and line L6 moves to it, so becomes the node of . Hence the pass visits the nodes of the nonempty prefixes , , each one time, and adds 1 to each of their counts. The only new nodes are those of prefixes of that were missing, which proves claim 1 for . A node gets exactly when is a nonempty prefix of , which proves claim 2. After the loop, is the node of (the root if were empty, which does not happen since ), and line L7 appends to its list. Since is larger than all earlier positions, the list stays increasing, which proves claim 3.
Theorem. After SUFFIX-TRIE-BUILD, the invariants (ST1), (ST2) and (ST3) of the page hold. For each string , FIND returns the node of if is a substring of , and NIL otherwise. For a nonempty , the count of that node is the number of occurrences of , and the union of the end lists in its subtree is the set of positions where occurs.
Proof. Apply the lemma with .
(ST1). A string is a substring of if and only if for some . If , this is a prefix of with . If , then . So the substrings of are exactly and the prefixes of , and claim 1 says that these are exactly the strings . With the uniqueness shown at the start, is a bijection.
(ST2). For a nonempty , " is a prefix of " holds if and only if and , that is, if and only if occurs at . With claim 2 this gives (ST2).
(ST3). This is claim 3. Each is appended exactly once, in pass .
FIND. The loop of lines L9 to L11 keeps the statement " is the node of the prefix of read so far". This holds at line L8, since the root is the node of . If the node of the prefix exists, it is the child of for , because and nodes are unique. If no such node exists, then is not a substring by (ST1), so is not one either (a substring of has all its prefixes as substrings), and line L11 returns NIL correctly. If the loop ends, line L12 returns the node of .
Occurrences. Let be the node of a nonempty . A node is in the subtree of if and only if is a prefix of . By (ST3), position is in the list of the node with , so is collected if and only if is a prefix of , that is, if and only if occurs at . Each position is in one list, so no position is reported twice.