Purpose: Build a suffix array in time. KΓ€rkkΓ€inen and Sanders (2003) β€” the first linear-time construction simple enough to fit on a page, and a much gentler read than SA-IS or Farach.

The Idea (β€œdifference cover mod 3”)

Split the positions by index mod 3:

  • = positions β€” two thirds of them;
  • = positions β€” one third.
  1. Recurse on . Form triples (s[i], s[i+1], s[i+2]) for , radix-sort and name them. Concatenate the names of the positions and then the positions into a string of length , and recursively compute its suffix array. That yields the correct order of all suffixes.
  2. Sort cheaply. A suffix at position is s[i] followed by the suffix at , which is in and therefore already ranked. So sort by the pair (character, known rank) with one radix sort β€” , no recursion.
  3. Merge. Comparing an suffix with an suffix takes : strip one or two characters until both indices land in , where ranks are known. That is exactly why works as a difference cover mod 3 β€” any two positions can be aligned into the recursed set within two steps.

Complexity

  • Time:
  • Space: , though with a larger constant than SA-IS

DC3 vs the alternatives

MethodTimeMemory constantImplementation difficulty
Prefix doubling (KMR) + sortsmalleasy
Prefix doubling + radix sortsmallmoderate
DC3 / skewmediummoderate β€” ~60 lines
SA-ISsmallhard β€” ~90 lines

What to actually use

prefix doubling handles comfortably and is far easier to write correctly at 2 a.m. Keep DC3 or SA-IS in your template library for the rare problem with .

Generalisation: difference covers

is a difference cover modulo 3: for every there exist in the set with . That property is exactly what makes step 3 constant-time. The same construction works modulo any with a difference cover of size β€” DC trades a bigger recursion base for less memory, and DC7 or DC13 are used in memory-constrained implementations.

Variants / Use Cases

  • Kasai β€” pair with any SA construction for the LCP array in
  • Suffix array β€” the topic page with applications
  • Difference cover sampling β€” also used for longest-common-extension queries in sublinear space
  • SA-IS β€” the faster linear-time alternative used by real libraries