A Lyndon word is a non-empty string that is strictly smaller than every one of its proper suffixes — equivalently, strictly smaller than all of its non-trivial rotations.

a, ab, aab, abb, aabab, abcbc are Lyndon. aa, aba, ba, abab are not.

Equivalent characterisations

  1. every proper suffix of .
  2. every non-trivial rotation of (so is the unique smallest rotation of itself, and is aperiodic).
  3. is a single character, or with Lyndon and (the standard factorisation).

The Chen-Fox-Lyndon theorem

Every string factors uniquely as with each Lyndon and .

Duval’s algorithm computes this factorisation in time and space.

What it is for

Smallest cyclic rotation

Run Duval on and take the factor that starts at a position and would extend past it. This is the standard , -space method — a competitor to Booth’s algorithm with shorter code.

int leastRotation(string s) {
    s += s;
    int n = s.size(), i = 0, ans = 0;
    while (i < n / 2) {
        ans = i;
        int j = i + 1, k = i;
        while (j < n && s[k] <= s[j]) { k = (s[k] < s[j]) ? i : k + 1; j++; }
        while (i <= k) i += j - k;
    }
    return ans;
}

De Bruijn sequences

The FKM algorithm (Fredricksen-Kessler-Maiorana): concatenate, in lexicographic order, every Lyndon word whose length divides . The result is a de Bruijn sequence — a cyclic string of length containing every length- string exactly once.

This is a strikingly clean construction; the alternative is an Eulerian circuit in the de Bruijn graph.

Generating all Lyndon words

Duval’s generation algorithm produces every Lyndon word of length in lexicographic order, in amortized per word:

void generate(int n, int sigma) {
    vector<int> w = {0};                     // start with the smallest
    while (!w.empty()) {
        output(w);
        int m = w.size();
        while ((int)w.size() < n) w.push_back(w[w.size() - m]);   // repeat periodically
        while (!w.empty() && w.back() == sigma - 1) w.pop_back();
        if (!w.empty()) w.back()++;
    }
}

The runs theorem

Every maximal repetition (run) in a string has a Lyndon root — a Lyndon word whose length is the run’s period. That observation is what proves a string has fewer than runs and gives the algorithm to find them all (Bannai et al., 2015).

Burrows-Wheeler transform

The bijective BWT is defined via the Lyndon factorisation, and Lyndon words are central to the theory of the ordinary BWT as well.

Counting Lyndon words

The number of Lyndon words of length exactly over an alphabet of size is

by Möbius inversion — the necklace-counting formula, restricted to aperiodic necklaces. This is the same identity that underlies the FKM construction.

Why competitive programmers should care

Three concrete payoffs:

  1. Smallest rotation in — a common subproblem when canonicalising cyclic strings.
  2. Lexicographically smallest / largest problems, where the greedy structure of Lyndon factorisation gives the answer directly.
  3. De Bruijn sequences, which appear in “find the code that opens the lock” style problems.

Beyond that, the border/period theory Lyndon words formalise is what makes prefix functions and periodicity arguments work.

See also: Duval’s Algorithm · Booth’s Algorithm · String Fundamentals