Proofs: Aho-Corasick algorithm
These are the human proofs of Aho-Corasick algorithm, at full length.
Aho-Corasick outputs each occurrence of each pattern exactly once full
This proof shows: correctness, termination.
Claim. For a text and patterns , AHO-CORASICK stops and outputs each pair with and exactly once, and outputs no other pair.
Setup. Let be the set of all prefixes of the patterns, including the empty string. After lines L1 to L3, the trie has one node for each string of , is the empty string, is defined exactly when , and is the list of the indices with , each index once. We call a pattern node when . The set is closed under prefixes: if , then . We write for the depth . For two suffixes of one string, the shorter is a suffix of the longer.
Lemma 1 (failure links). For each node , is the node of the longest proper suffix of that lies in . Moreover, the nodes whose strings are proper suffixes of are exactly , ending at the root, in decreasing order of depth.
Proof. By induction on . The breadth-first order of lines L4 to L13 dequeues all nodes of depth before any node of depth , and the link of a node of depth is set when its parent, of depth , is dequeued. So when is set, the links of all nodes of depth at most are already set.
Depth 1. The only proper suffix of a one-character string is the empty string, and line L4 sets . The chain is the root alone.
Depth . Let , so and . A nonempty proper suffix of has the form , where is a proper suffix of . If , then . So the nonempty candidates are the strings with a proper suffix of in and defined. By the induction hypothesis for , these strings are the chain , in decreasing order of length. Lines L9 to L11 walk this chain from the start and stop at the first node with defined, or at the root. If is defined, it is the longest candidate; it is not itself, because . If not, then is the root and no candidate exists, and the longest proper suffix in is the empty string. Line L12 sets to the right node in both cases.
For the chain, let be a proper suffix of in , and let . By the first part, . If , then . If , then is a proper suffix of , and , so by the induction hypothesis is on the chain of . Conversely, each node of the chain spells a proper suffix of , by transitivity of the suffix relation. Each link strictly lowers the depth, so the chain is in decreasing order of depth and ends at the root.
Lemma 2 (dictionary links). For each node , is the pattern node of the longest proper suffix of that is a pattern, or nil if no proper suffix is a pattern. Hence the sequence (up to nil) lists all pattern nodes whose strings are proper suffixes of , in decreasing order of depth, each once.
Proof. For the root, is nil, and the empty string has no proper suffix. For , line L7 runs when is dequeued. Then has smaller depth, so it is the root or a node dequeued before , and its value is final. By Lemma 1, the proper suffixes of in are and the proper suffixes of in . Each pattern is in . So the longest proper suffix of that is a pattern is if is a pattern node, and else the longest proper suffix of that is a pattern, which is by induction on depth. This is line L7. The second statement follows by applying the first one to , then to , and so on; the depth strictly falls, so the sequence ends.
Lemma 3 (REPORT). REPORT outputs the pair for each such that is a suffix of , each pair once, and nothing else.
Proof. The patterns that are suffixes of are itself, if is a pattern node, and the patterns among its proper suffixes. Line L19 starts the walk at in the first case and at in the second. If is a pattern node, lists exactly the remaining ones (Lemma 2). So the loop of lines L20 to L22 visits each pattern node whose string is a suffix of exactly once, and line L21 outputs each index stored at it. Each index is stored at exactly one node, the node of .
Lemma 4 (search invariant). For , let be the longest suffix of that lies in . When REPORT is called, .
Proof. By induction on . For , the text read is empty, is the empty string, and line L14 calls REPORT with the root.
Assume the claim for , with the node of , and let . A nonempty suffix of in has the form with a suffix of and (prefix closure). Then , so is a suffix of : it is or a proper suffix of it in , that is, or a node of the failure chain of (Lemma 1). Line L16 walks in decreasing order of depth, and stops at the first node with a child along , or at the root. If that node has the child, the child spells the longest suffix of in , and line L17 moves there. If not, the walk stopped at the root and no candidate exists, so is empty and line L17 sets to the root. Line L18 then calls REPORT with the node of .
Termination. The loop of lines L10 and L11 and the loop of line L16 each lower the depth of a node by at least 1 at each pass, and depths are non-negative integers, so they stop. The loop of line L20 lowers the depth at each pass by Lemma 2. The other loops run over finite sets. So the algorithm stops.
Theorem. The claim holds.
Proof. Each call REPORT outputs pairs with a suffix of (Lemmas 3 and 4), and is a suffix of . So , and each output pair is an occurrence.
Conversely, let be an occurrence and , so . Then is a suffix of , and . By the definition of , , so is a suffix of . The search calls REPORT exactly once with the end position , at line L14 if and at line L18 with otherwise, and by Lemma 3 this call outputs exactly once. Other calls have another end position, so they do not output .