Algorithm Search⌘K

Proofs: Compressed suffix tree

These are the human proofs of Compressed suffix tree, at full length.

The range operations of the compressed suffix tree return the right nodes full

This proof shows: correctness, termination, time.worst.

Setting. T$T\$ has N=n+1N = n + 1 suffixes, $\$ is unique and smallest, and ranks and positions are 0-based. SrS_r is the suffix of rank rr. LCP[r]=lcp(Sr−1,Sr)LCP[r] = \mathrm{lcp}(S_{r-1}, S_r) for 1≤r≤n1 \le r \le n, and LCP[0]=LCP[N]=−1LCP[0] = LCP[N] = -1. Since $\$ is unique, no suffix is a prefix of another, so every suffix ends at its own leaf of the suffix tree, and for r≥1r \ge 1, LCP[r]<min⁡(∣Sr−1∣,∣Sr∣)LCP[r] < \min(|S_{r-1}|, |S_r|).

Fact (LCP-RMQ). For a<ca < c, lcp(Sa,Sc)=min⁡LCP[a+1…c]\mathrm{lcp}(S_a, S_c) = \min LCP[a+1 \ldots c]. This is the lemma of the LCP-RMQ reduction.

Lemma 1 (nodes). For a string uu that labels a node of the suffix tree, the set of ranks of the suffixes that start with uu is a range [lb..rb][lb..rb]. If the node is internal and u≠εu \ne \varepsilon, then ℓ=∣u∣\ell = |u| satisfies LCP[r]≥ℓLCP[r] \ge \ell for lb<r≤rblb < r \le rb, LCP[r]=ℓLCP[r] = \ell for some such rr, and LCP[lb]<ℓLCP[lb] < \ell, LCP[rb+1]<ℓLCP[rb+1] < \ell. Conversely, every range with these properties, for some ℓ≥1\ell \ge 1, is the range of a node of depth ℓ\ell. The root is [0..n][0..n], and a leaf is [r..r][r..r].

Proof. The suffixes that start with uu are consecutive in sorted order. By the fact, min⁡LCP[lb+1…rb]=lcp(Slb,Srb)\min LCP[lb+1 \ldots rb] = \mathrm{lcp}(S_{lb}, S_{rb}), which is at least ℓ\ell; it is exactly ℓ\ell because uu is followed by at least two different symbols, and the smallest and the largest suffix in the range have the smallest and the largest of them. Slb−1S_{lb-1} and Srb+1S_{rb+1} do not start with uu, so their lcp with the range is less than ℓ\ell. Conversely, the suffixes of such a range share their first ℓ\ell symbols uu, two of them differ at depth ℓ\ell, and the neighbors outside do not start with uu; so uu is a node and the range is exactly its set. □\square

Lemma 2 (enclosing node). Let 1≤k≤n1 \le k \le n and h=LCP[k]≥0h = LCP[k] \ge 0. The range [PSV(k)..NSV(k)−1][\mathrm{PSV}(k)..\mathrm{NSV}(k) - 1] is the node of depth hh that contains the ranks k−1k - 1 and kk. Here PSV(k)≥0\mathrm{PSV}(k) \ge 0 and NSV(k)≤N\mathrm{NSV}(k) \le N exist because LCP[0]=LCP[N]=−1LCP[0] = LCP[N] = -1.

Proof. Let a=PSV(k)a = \mathrm{PSV}(k) and c=NSV(k)c = \mathrm{NSV}(k). All values in LCP[a+1…c−1]LCP[a+1 \ldots c-1] are at least hh, the value LCP[k]=hLCP[k] = h is among them, and LCP[a]<hLCP[a] < h, LCP[c]<hLCP[c] < h. If h≥1h \ge 1, Lemma 1 gives a node of depth hh with the range [a..c−1][a..c-1], which contains k−1≥ak - 1 \ge a and k≤c−1k \le c - 1. If h=0h = 0, all values between are at least 0, which holds for all 1≤r≤n1 \le r \le n, so a=0a = 0 and c=Nc = N, and the range is the root. □\square

Theorem 1 (depth). CST-DEPTH returns the string depth.

Proof. A leaf [r..r][r..r] has the label SrS_r, of length N−SA[r]N - SA[r]. An internal node has depth min⁡LCP[lb+1…rb]\min LCP[lb+1 \ldots rb] by Lemma 1, and RMQ returns a position of that minimum. □\square

Theorem 2 (parent). For a node v=[lb..rb]v = [lb..rb] other than the root, CST-PARENT returns its parent.

Proof. Let h=max⁡(LCP[lb],LCP[rb+1])h = \max(LCP[lb], LCP[rb+1]). Since vv is not the root, lb≥1lb \ge 1 or rb≤n−1rb \le n - 1, so h≥0h \ge 0. Let kk be the border with the value hh. By Lemma 2, p=[PSV(k)..NSV(k)−1]p = [\mathrm{PSV}(k)..\mathrm{NSV}(k) - 1] is the node of depth hh that contains k−1k - 1 and kk, so it contains a rank of vv and a rank outside vv; as nodes are nested or disjoint, pp strictly contains vv. Every node that strictly contains vv is a larger range, so it contains lblb and lb−1lb - 1, or rbrb and rb+1rb + 1. In the first case its depth is at most lcp(Slb−1,Slb)=LCP[lb]≤h\mathrm{lcp}(S_{lb-1}, S_{lb}) = LCP[lb] \le h, and in the second at most LCP[rb+1]≤hLCP[rb+1] \le h. The nodes that contain vv form a chain, so pp, which has the largest possible depth hh, is the deepest of them: the parent. □\square

Theorem 3 (children). For an internal node v=[lb..rb]v = [lb..rb] of depth ℓ\ell, with ℓ\ell-indices k1<⋯<ktk_1 < \cdots < k_t, CST-FIRST-CHILD returns [lb..k1−1][lb..k_1 - 1], and CST-NEXT-SIBLING maps [ki..ki+1−1][k_i..k_{i+1} - 1] to the next child and returns nil for the last child [kt..rb][k_t..rb].

Proof. The children of an lcp-interval are the ranges between its ℓ\ell-indices, as on the LCP interval tree page. The minimum of LCP[lb+1…rb]LCP[lb+1 \ldots rb] is ℓ\ell, and the leftmost position with it is k1k_1, which gives L5. For a child w=[x..y]w = [x..y], the parent of ww has the depth max⁡(LCP[x],LCP[y+1])\max(LCP[x], LCP[y+1]) by Theorem 2. If ww is not the last child, then y+1y + 1 is an ℓ\ell-index, so LCP[y+1]=ℓ≥LCP[x]LCP[y+1] = \ell \ge LCP[x], and the test of L6 fails. The next child starts at y+1y + 1 and ends just before the next ℓ\ell-index or at rbrb, that is, just before the first r>y+1r > y + 1 with LCP[r]≤ℓLCP[r] \le \ell, because inside vv all values are at least ℓ\ell and LCP[rb+1]<ℓLCP[rb+1] < \ell. If ww is the last child, then w=[kt..rb]w = [k_t..rb], since an internal node has at least two children, so LCP[x]=ℓ>LCP[rb+1]LCP[x] = \ell > LCP[rb+1] and L6 returns nil. For the root, L6 returns nil at once. □\square

Theorem 4 (LCA). For nodes uu and vv with rb(u)<lb(v)rb(u) < lb(v), CST-LCA returns their lowest common ancestor.

Proof. Let kk be the leftmost minimum of LCP[rb(u)+1…lb(v)]LCP[rb(u)+1 \ldots lb(v)] and h=LCP[k]h = LCP[k]. The values inside uu are at least the depth of uu, which is larger than LCP[rb(u)+1]≥hLCP[rb(u)+1] \ge h when uu is internal, and the same holds for vv; so h=min⁡LCP[lb(u)+1…rb(v)]h = \min LCP[lb(u)+1 \ldots rb(v)], the lcp of every suffix of uu with every suffix of vv that are the farthest apart. By Lemma 2, [PSV(k)..NSV(k)−1][\mathrm{PSV}(k)..\mathrm{NSV}(k) - 1] is the node of depth hh around kk; it contains [lb(u)..rb(v)][lb(u)..rb(v)] because no value in that range is below hh. A common ancestor contains rb(u)rb(u) and lb(v)lb(v), so its depth is at most lcp(Srb(u),Slb(v))=h\mathrm{lcp}(S_{rb(u)}, S_{lb(v)}) = h. So this node is the deepest common ancestor. □\square

Theorem 5 (suffix link). For an internal node v=[lb..rb]v = [lb..rb] with label cucu, CST-SUFFIX-LINK returns the node of uu.

Proof. SlbS_{lb} and SrbS_{rb} start with cucu, and they differ at depth ∣cu∣|cu| (Lemma 1 with the fact). Ψ\Psi maps them to the suffixes one position later, which start with uu and differ at depth ∣u∣|u|. So the LCA of the leaves Ψ(lb)\Psi(lb) and Ψ(rb)\Psi(rb) has depth ∣u∣|u| by Theorem 4 and its proof, and its label is uu. Since Ψ\Psi keeps the order of suffixes with the same first symbol, Ψ(lb)<Ψ(rb)\Psi(lb) < \Psi(rb) and the leaves are disjoint, so Theorem 4 applies. A leaf Sr=c S′S_r = c\,S' with c≠$c \ne \$ links to the leaf of S′S', which has the rank Ψ(r)\Psi(r); the leaf $\$ links to the root, whose label is empty. □\square

Lemma 3 (H). PLCP[p+1]≥PLCP[p]−1PLCP[p+1] \ge PLCP[p] - 1 for 0≤p<n0 \le p < n. Hence the numbers PLCP[p]+2pPLCP[p] + 2p strictly increase with pp, and the one of HH with index pp, counting from 0, is at PLCP[p]+2pPLCP[p] + 2p.

Proof. If PLCP[p]=h≥1PLCP[p] = h \ge 1, the suffix at pp has a previous suffix qq in sorted order that shares hh symbols. Then the suffix at q+1q + 1 is smaller than the suffix at p+1p + 1 and shares h−1h - 1 symbols with it, and by the fact every suffix between them in sorted order, in particular the previous suffix of p+1p + 1, shares at least h−1h - 1 symbols. So PLCP[p+1]≥h−1PLCP[p+1] \ge h - 1, which also holds when h=0h = 0. Then PLCP[p+1]+2(p+1)≥PLCP[p]+2p+1PLCP[p+1] + 2(p+1) \ge PLCP[p] + 2p + 1. □\square

Letter and find. By Lemma 1, all suffixes of vv share the label of vv, so the symbol at depth dd is T$[SA[lb]+d]T\$[SA[lb] + d], the first symbol of the suffix of rank SA−1[SA[lb]+d]SA^{-1}[SA[lb] + d]. Find walks the tree as in a suffix tree: at each node it picks the unique child whose edge starts with the next symbol, and compares the edge with the pattern.

Time and termination. Every scan in a block, every walk in the tree of minima, every select and every chain of Ψ\Psi steps is bounded: by bb, by 2log⁡22 \log_2 of the number of blocks, by the distance between two sampled ones of HH, and by ss. PSV and NSV always find an answer for h≥0h \ge 0, because of the border values −1-1. So each operation ends, in the times given on the page. ■\blacksquare

Back to Compressed suffix tree