Algorithm Search⌘K

Proofs: LOUDS trie

These are the human proofs of LOUDS trie, at full length.

The LOUDS formulas find the children and the parent of a node, and the LOUDS trie answers membership correctly full

This proof shows: correctness, complexity.

We use the pseudocode, the notation and the invariant (L1) to (L4) of the page. Let dxd_x be the number of children of node xx, and Dx=d0+⋯+dx−1D_x = d_0 + \cdots + d_{x-1}.

Lemma 1 (breadth-first numbering). The children of node xx are the nodes 1+Dx,…,Dx+dx1 + D_x, \ldots, D_x + d_x, in order of their labels.

Proof. Breadth-first order with a queue visits the nodes in the order they are enqueued, and the children of each node are enqueued, in label order, when the node is visited. The root is node 0, and the nodes enqueued before the children of xx are the root and the children of nodes 0,…,x−10, \ldots, x - 1, which are 1+Dx1 + D_x nodes. □\square

Lemma 2 (layout). B=10 1d00 1d10⋯1dn−10B = 10\, 1^{d_0} 0\, 1^{d_1} 0 \cdots 1^{d_{n-1}} 0. Before the group of xx there are x+1x + 1 zeros (the zero of 1010 and the closing zeros of nodes 0,…,x−10, \ldots, x - 1) and 1+Dx1 + D_x ones.

Proof. By construction, the group of xx follows the prefix 1010 and the groups of nodes 0,…,x−10, \ldots, x - 1, each closed by one 0. Counting the bits of these parts gives the claim. □\square

CHILDREN. By Lemma 2 the (x+1)(x + 1)-th 0 is the bit just before the group of xx, and the (x+2)(x + 2)-th 0 closes it. So a=select0(x+1)+1a = select_0(x + 1) + 1 and e=select0(x+2)e = select_0(x + 2) delimit the group, and e−a=dxe - a = d_x. The number of 1s before aa is 1+Dx1 + D_x, so first=rank1(a)=1+Dxfirst = rank_1(a) = 1 + D_x and last=first+dxlast = first + d_x. By Lemma 1 these are the children of xx.

PARENT. Let x≥1x \ge 1 be a child of qq. The 1s of BB are, in order, the leading 1 and the groups of nodes 0,1,…0, 1, \ldots; by Lemma 1 the jj-th 1 of the groups, for j≥1j \ge 1, is node jj. So the (x+1)(x + 1)-th 1 of BB lies in the group of qq, at position p=select1(x+1)p = select_1(x + 1). By Lemma 2 there are exactly q+1q + 1 zeros before any position of the group of qq, so rank0(p)−1=qrank_0(p) - 1 = q.

CHILD and CONTAINS. By (L3) the labels L[first…last−1]L[first \ldots last - 1] are distinct and sorted, so the binary search finds the child with label cc if it exists, and reports NIL otherwise. CONTAINS starts at the root, whose string is empty, and line L5 keeps the claim that xx is the node whose string is the part of ss read so far: CHILD returns the child by the next symbol, whose string extends it by that symbol. If some child is missing, no node spells the read part, and since every key is the string of a node (the pointer trie built at line L7 has a node for each prefix of each key), ss is not a key. If the walk ends, xx spells ss, and by construction E[x]E[x] is set exactly when ss is a key.

Complexity. CHILDREN and PARENT use two select or rank operations, which take O(1)O(1) time with a constant-time index. CHILD adds a binary search over at most σ\sigma labels, O(log⁡σ)O(\log \sigma). CONTAINS makes mm calls of CHILD, O(mlog⁡σ)O(m \log \sigma). BB has nn ones and n+1n + 1 zeros, so 2n+12n + 1 bits. ■\blacksquare

Back to LOUDS trie