Proofs: Position heap
These are the human proofs of Position heap, at full length.
The position heap keeps its invariant, and SEARCH reports exactly the occurrences of the pattern full
This proof shows: correctness, complexity.
We use the pseudocode, the notation and the invariant (H1) to (H3) of the page. Write for the suffix at , and for the node with .
Lemma 1 (PREPEND). If the heap of satisfies (H1) to (H3), then after PREPEND(c) the heap satisfies them for .
Proof. Each old node keeps its string and its suffix, which now starts at a position one larger; so (H2) still holds for the old nodes, and the old positions become . The walk of line L2 follows the symbols of while the nodes exist. It stops at some depth : if it reached depth , the node of itself would exist, and its holder would satisfy , against (H2). So exists, and line L3 adds the node with , a prefix of , and . This gives (H1) and (H2) for . The new node is a leaf, and its parent is the root or an old node with position at least 1, so (H3) holds.
By induction, the heap built by calls of PREPEND satisfies (H1) to (H3). The trie has distinct symbols at the children of each node, so the walk along a string is unique, and for each string there is at most one node with ; if such a node exists, so does the node of every prefix of , its ancestor.
Lemma 2 (where an occurrence is). Let occur at . Then either is a proper prefix of , or is a prefix of .
Proof. By (H2) is a prefix of , and is a prefix of since it occurs at . Two prefixes of the same string are comparable under the prefix order.
SEARCH is correct. Let $u_0 = $ root, be the nodes of the walk of line L4, with ; the walk stops at or at a node with no child by .
Every reported position is an occurrence. Line L5 reports a position only after checking it. Line L6 runs only if ; then , and every node of the subtree of has as a prefix of , which is a prefix of by (H2), so occurs at .
Every occurrence is reported. Let occur at . By Lemma 2 there are two cases. If is a proper prefix of , of length , then the node of is , and since its ancestors exist the walk reaches it: with and . Line L5 checks and reports it. If is a prefix of , then the node of exists, as an ancestor of or itself, so the walk reaches depth , is the node of , and is in its subtree; line L6 reports .
No position is reported twice. The nodes checked at line L5 have depth less than and the nodes of line L6 have depth at least , and each node holds one position by (H1).
Complexity. The walk takes at most steps. Line L5 makes at most checks of at most symbols each. Line L6 visits the subtree of , and each of its nodes is an occurrence, so with occurrences it takes time. The total is . By (H1) the heap has nodes, so it takes words.