The vocabulary and the theory that the algorithms rest on.
Definitions
| Term | Meaning |
|---|---|
| Substring | a contiguous block, |
| Subsequence | any subset of positions, order preserved (not contiguous) |
| Prefix | · Proper prefix: not the whole string |
| Suffix | |
| Border | a string that is both a proper prefix and a proper suffix |
| Period | for all valid |
| Rotation | |
| Palindrome | equal to its own reverse |
A string of length has substrings (not all distinct) and subsequences.
The border-period duality
has a border of length iff has a period .
This single equivalence is why the prefix function — which computes the longest border of every prefix — is such a powerful primitive. It answers questions about periodicity for free.
All periods. Following the border chain enumerates every border, hence every period, in .
Smallest period. . The string is a full repetition of that period iff .
int smallestPeriod(const string& s) {
vector<int> pi = prefixFunction(s);
return s.size() - pi.back();
}
bool isRepetition(const string& s) {
int p = smallestPeriod(s);
return p != (int)s.size() && s.size() % p == 0;
}The periodicity lemma (Fine and Wilf)
If has periods and with , then it also has period .
The bound is tight. This lemma underlies the linear-time constant-space matching algorithms (Galil-Seiferas, Crochemore-Perrin) and the analysis of runs.
Lexicographic order
Compare character by character; if one string is a prefix of the other, the shorter one is smaller. Note that lexicographic order is not length order — "z" > "abc".
- Smallest rotation — Booth’s algorithm or Duval, .
- Comparing substrings in — hashing plus binary search on the LCP, or a suffix array with rank arrays.
- -th lexicographic substring — descend a suffix automaton with subtree counts.
Counting distinct substrings
| Method | Complexity |
|---|---|
| Suffix array + LCP | , |
| Suffix automaton | , |
| Hashing + a set per length | |
| Trie of all suffixes |
The suffix automaton formula is the cleanest: each state represents a set of substrings of consecutive lengths, and their count is exactly .
Runs and repetitions
A run is a maximal periodic substring with period .
The runs theorem (Bannai et al., 2015): a string of length has fewer than runs, and they can all be found in .
Runs are found via Lyndon roots plus longest-common-extension queries. The older Main-Lorentz divide and conquer is easier to implement and usually sufficient.
Choosing a tool
| Task | Tool |
|---|---|
| Find one pattern in a text | KMP, Z, or hashing |
| Find many patterns | Aho-Corasick |
| Compare arbitrary substrings | hashing, or suffix array + LCP |
| Count distinct substrings | suffix automaton |
| Longest common substring of two strings | suffix automaton of one, run the other through it |
| All palindromic substrings | Eertree or Manacher |
| Periods and borders | prefix function |
| Smallest rotation | Booth or Duval |
| -th substring lexicographically | suffix automaton |
See also: Prefix Function · String Hashing · Strings