Algorithm Search⌘K

Proofs: Longest common substring via suffix tree

These are the human proofs of Longest common substring via suffix tree, at full length.

The deepest node with both marks spells a longest common substring full

This proof shows: correctness.

Let S=A#B$S = A \# B \$ with #,$∉Σ\#, \$ \notin \Sigma and #≠$\# \ne \$, and let a=∣A∣a = \lvert A \rvert. The suffix of SS at position pp is an AA-suffix if p≤ap \le a and a BB-suffix if p>ap > a. We use these facts about the suffix tree of SS: since $\$ occurs only at the end, no suffix is a prefix of another, so each suffix is the path label of exactly one leaf; for each node vv, the leaves below vv are the suffixes that have label(v)label(v) as a prefix; and every string that is a prefix of some suffix ends either at a node or inside an edge, and in the second case the leaves below that point are those below the lower end of the edge.

Lemma 1 (marks). After line L5, mark(v)mark(v) is the set of kinds of the suffixes that have label(v)label(v) as a prefix.

Proof. By induction in postorder. A leaf gets the kind of its own suffix at line L4. An inner node gets the union over its children, and the leaves below vv are the union of the leaves below its children. □\square

Lemma 2 (common prefixes stay inside the strings). Let XX be a common prefix of an AA-suffix S[p..]S[p ..] and a BB-suffix S[q..]S[q ..], with X≠εX \neq \varepsilon. Then p+∣X∣≤ap + \lvert X \rvert \le a and X=A[p..p+∣X∣−1]=B[q−a−1..q−a−2+∣X∣]X = A[p .. p + \lvert X \rvert - 1] = B[q - a - 1 .. q - a - 2 + \lvert X \rvert], so XX is a common substring of AA and BB.

Proof. The BB-suffix S[q..]S[q ..] contains no #\#, and its only $\$ is its last symbol. If XX contained #\#, so would the BB-suffix, which is impossible. If XX contained $\$, then $\$ would be the last symbol of the BB-suffix's prefix XX, so XX would be the whole BB-suffix; but XX is also a prefix of the AA-suffix, in which $\$ occurs only at the end after a #\# (or, if p=ap = a, the AA-suffix starts with #\#, and then the first symbols already differ, since S[q]≠#S[q] \ne \#). In both cases XX would contain #\#, which was excluded. So XX lies in Σ∗\Sigma^*. Since the AA-suffix has its first symbol outside Σ\Sigma at position aa, the prefix XX ends before it: p+∣X∣≤ap + \lvert X \rvert \le a. Likewise, XX ends before the $\$ of the BB-suffix. □\square

Lemma 3 (every common substring is seen). If X≠εX \neq \varepsilon occurs in AA at ii and in BB at jj, then there is a node vv with mark(v)={A,B}mark(v) = \{A, B\} and depth(v)≥∣X∣depth(v) \ge \lvert X \rvert.

Proof. The AA-suffix at ii and the BB-suffix at a+1+ja + 1 + j both start with XX. Let vv be the node where XX ends, or the lower end of the edge inside which XX ends. Its label has XX as a prefix, so depth(v)≥∣X∣depth(v) \ge \lvert X \rvert, and the leaves below vv are the suffixes that start with label(v)label(v). Because XX ends at vv or inside the edge into vv, every suffix that starts with XX continues along that edge and so starts with label(v)label(v): both leaves are below vv, and by Lemma 1, mark(v)={A,B}mark(v) = \{A, B\}. □\square

Theorem. Line L7 returns (ℓ,i,j)(\ell, i, j) where ℓ\ell is the length of a longest common substring of AA and BB, and A[i..i+ℓ−1]=B[j..j+ℓ−1]A[i .. i + \ell - 1] = B[j .. j + \ell - 1].

Proof. If v≠v \ne root has mark(v)={A,B}mark(v) = \{A, B\}, then vv is an inner node (a leaf has one kind), and by Lemma 1 some AA-suffix S[p..]S[p ..] and some BB-suffix S[q..]S[q ..] have label(v)label(v) as a prefix. By Lemma 2, label(v)label(v) is a common substring, found at pp in AA and at q−a−1q - a - 1 in BB; these are the positions that line L7 reports for v∗v^*. So best≤ℓ∗best \le \ell^*, the length of a longest common substring. If ℓ∗>0\ell^* > 0, Lemma 3 applied to a longest common substring gives a node with both marks and depth at least ℓ∗\ell^*, so best≥ℓ∗best \ge \ell^*. Line L6 keeps the maximum of depthdepth over all such nodes, since the walk visits every node, so best=ℓ∗best = \ell^*. If ℓ∗=0\ell^* = 0, Lemma 2 shows that no node other than the root has both marks, because its label would be a nonempty common substring. The root has depth 0, and line L6 does not choose it since bestbest starts at 0, so line L7 returns (0,0,0)(0, 0, 0). ■\blacksquare

Back to Longest common substring via suffix tree