Kasai's algorithm computes the LCP array in linear time 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 KASAI, 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 (KASAI). 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 KASAI 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. Line L1 takes Θ(n) time. ■