LCP-BUILD computes the LCP array, and the queries return the LCP of two suffixes full
This proof shows: correctness, termination, time.worst.
Notation. T=T[0…n−1], n≥1, and Tp=T[p…n−1] for 0≤p≤n, so Tn is the empty string. The order < on strings is the lexicographic order in which a proper prefix is smaller. SA lists T0,…,Tn−1 in increasing order, and RANK is its inverse. For RANK[p]>0 let pred(p)=SA[RANK[p]−1] and ℓ(p)=lcp(Tpred(p),Tp). The claim is that after LCP-BUILD, LCP[0]=0 and LCP[RANK[p]]=ℓ(p) for each p with RANK[p]>0.
Lemma 1 (sandwich). If x≤y≤z, then lcp(x,z)≤lcp(x,y) and lcp(x,z)≤lcp(y,z).
Proof. Let k=lcp(x,z) and c=x[0…k−1]=z[0…k−1]. Suppose that y does not start with c, and let j<k be the first index where y and c differ: either ∣y∣=j, or y[j]=c[j]. If ∣y∣=j or y[j]<c[j], then y<x, because x starts with c and so x is longer than j and agrees with y before j. If y[j]>c[j], then y>z for the same reason. Both contradict x≤y≤z. So y starts with c, and both inequalities follow. □
Lemma 2 (drop one symbol). Let RANK[p]>0 and ℓ(p)=h≥2. Then p+1<n, RANK[p+1]>0 and ℓ(p+1)≥h−1.
Proof. Let q=pred(p). Both Tq and Tp have length at least h≥2 and T[q]=T[p]. Then Tq+1 and Tp+1 are Tq and Tp without their equal first symbol. They are nonempty, they share a prefix of length h−1, and Tq+1<Tp+1, because removing an equal first symbol keeps the order. So Tp+1 is not the smallest suffix, which gives RANK[p+1]>0. The suffix Tpred(p+1) is the largest suffix below Tp+1, so Tq+1≤Tpred(p+1)<Tp+1. By Lemma 1, ℓ(p+1)=lcp(Tpred(p+1),Tp+1)≥lcp(Tq+1,Tp+1)≥h−1. □
Theorem 1 (LCP-BUILD). Line L1 makes RANK the inverse of SA. Then the loop of line L3 keeps this invariant at the start of round p:
(K) For each p′<p, the entry LCP[RANK[p′]] holds 0 if RANK[p′]=0 and ℓ(p′) otherwise. Also 0≤h, and if RANK[p]>0 then h≤ℓ(p). If h≥1, then RANK[p]>0.
Initialization. At p=0 no entry is claimed, and h=0 by line L2.
Maintenance. If RANK[p]=0, then by (K) h=0, line L4 writes LCP[0]=0 and keeps h=0, and h=0 satisfies (K) for p+1. Otherwise line L5 sets q=pred(p). Since h≤ℓ(p), the first h symbols of Tp and Tq are equal. Line L6 increases h while the next symbols exist and are equal, so it stops exactly at h=ℓ(p). Line L7 writes the right value. Line L8 sets h=max(ℓ(p)−1,0). If ℓ(p)≥2, Lemma 2 gives RANK[p+1]>0 and h=ℓ(p)−1≤ℓ(p+1). If ℓ(p)≤1, then h=0. In both cases (K) holds at the start of round p+1.
Termination. The loop runs for p=0,…,n−1 and stops. Each inner loop stops, because h grows by 1 in each step and is bounded by n−p. At the end, (K) with p=n covers every position, and RANK is a bijection onto the indices 0,…,n−1, so every entry of LCP is right. □
Theorem 2 (time). Line L6 increases h at most 2n times in total, so LCP-BUILD takes Θ(n) time.
Proof. The value h is at most n at all times. It decreases only at line L8, by 1, at most once in each of the n rounds. Line L4 does not change it, because h=0 there by (K). So the number of increases is at most the final value plus the number of decreases, which is at most n+n. Each round does O(1) other work, and the failed test that ends line L6 costs O(1) for each round. □
Lemma 3 (LCP of two ranks). For 0≤i<j<n, lcp(TSA[i],TSA[j])=minLCP[i+1…j].
Proof. Write Sk=TSA[k] and m=minLCP[i+1…j]. For any strings, lcp(x,z)≥min(lcp(x,y),lcp(y,z)), because x and y agree on the first lcp(x,y) symbols, and y and z on the first lcp(y,z). Applying this along Si,Si+1,…,Sj gives lcp(Si,Sj)≥m. For the other direction, pick k with i<k≤j and LCP[k]=m. Since Si≤Sk−1<Sk≤Sj, Lemma 1 applied twice gives lcp(Si,Sj)≤lcp(Sk−1,Sj)≤lcp(Sk−1,Sk)=m. □
Theorem 3 (queries). LCP-RANKS(i,j) returns lcp(TSA[i],TSA[j]) for 0≤i<j<n, and LCE(p,q) returns lcp(Tp,Tq) for 0≤p,q<n.
Proof. By induction on k, M[k][i]=minLCP[i…i+2k−1]: for k=0 it is LCP[i], and the range of length 2k is the union of the two ranges of length 2k−1 that start at i and at i+2k−1. In line L9, L=j−i≥1 and 2k≤L<2k+1. The ranges [i+1,i+2k] and [j−2k+1,j] lie inside [i+1,j], and since 2k+1≥L+1 the second starts no later than one place after the end of the first, so together they cover [i+1,j]. The minimum over a union is the minimum of the two minima, so line L10 returns minLCP[i+1…j], which is the claim by Lemma 3. For LCE, if p=q the answer is ∣Tp∣=n−p (line L11). Otherwise lines L12 and L13 call LCP-RANKS with the two ranks in increasing order, and TSA[RANK[p]]=Tp. ■