Algorithm

int[] kasai(String s, int[] sa) {
  int n = s.length();
  int[] rank = new int[n], lcp = new int[n];
  for (int i = 0; i < n; i++) rank[sa[i]] = i;
  int h = 0;
  for (int i = 0; i < n; i++) {
    if (rank[i] > 0) {
      int j = sa[rank[i] - 1];
      while (i + h < n && j + h < n && s.charAt(i + h) == s.charAt(j + h)) h++;
      lcp[rank[i]] = h;
      if (h > 0) h--;
    } else h = 0;
  }
  return lcp;
}
Advertisement

Why O(N)

h decreases by at most 1 per iteration. Total increments = O(N). Total decrements = O(N).

Advertisement

Applications

Longest repeated substring = max LCP. Distinct substrings via LCP sum. Range min queries on LCP → LCP between any two suffixes.

LCP RMQ

Preprocess LCP with sparse table → LCP(i,j) in O(1) via RMQ of LCP[min+1..max].