It’s been a while since I last wrote a post. I recently spent some time on suffix arrays and learned a lot, so I wanted to write this up as a keepsake. Credit where it’s due — the template used below is YZH’s SAIS implementation, and the section titles and example problems come from Luo Suiqian’s 2009 IOI national team paper. Respect.
Problems on a Single String
Longest Non-Overlapping Repeated Substring
Sort all suffixes, then binary-search the answer. For a candidate length , group the sorted suffixes so that every group has
lcp(height)at least . Within each group, track the maximum and minimum ofrl(sa); if their difference exceeds , a non-overlapping repeated substring of length exists. This is . You can also do it in by using two pointers together with a monotonic deque to maintain the max/min ofrl(sa); the answer is the largestlcp(height)seen across valid groups.
Musical Theme
Longest Repeated Substring Occurring at Least Times (Overlapping Allowed)
The same binary-search-on- approach works: check whether some group with
lcp(height) >= lcontains at least suffixes. That’s . It also runs in with two pointers by sliding a window of exactly consecutive suffixes.
Milk Patterns
Number of Distinct Substrings
Notice that for the suffix ranked -th, all substrings starting at
rl[i]and ending at or beforelcp[i]characters into the suffix would be double-counted. Subtracting those out, the answer is computable in .
DISUBSTR - Distinct Substrings
Longest Palindromic Substring
Reverse the string, concatenate it to the original with an unused separator in the middle, then run suffix array on the combined string. Enumerate center points (splitting into odd/even-length cases) and combine with -table range-min on the height array. Precomputation is ; querying is , so total . If you replace the table with Cartesian tree + Tarjan for RMQ with preprocessing, the whole solution becomes .
Palindrome
Continuous Repetition Detection
Observation: if a string is the concatenation of copies of a period of length , then . Enumerate the divisors of and use the -table to check the ; that’s . If you notice that one endpoint of the RMQ is always fixed, you can precompute in and drop the .
Power Strings
Substring with Maximum Number of Continuous Repetitions
Enumerate period length . For any candidate period, positions must fall inside a run of length- repeats. For adjacent samples and , their gives the maximum stretch to the right; if isn’t a multiple of , check whether pushing the start one step to the left adds one more copy. The complexity works out to
Maximum repetition substring
REPEATS - Repeats
Problems on Two Strings
Longest Common Substring
Concatenate the two strings with an unused separator, then run suffix array on the combined string. The longest common substring must appear as the of two adjacent suffixes that come from different original strings. .
Long Long Message
Freedom of Choice
Count of Common Substrings of Length at Least
Concatenate as above and run suffix array. For each suffix of , count contributions from previously seen suffixes of , then swap roles and do the same. A monotonic stack keeps the running sum in amortized per suffix, giving overall.
Common Substrings
Problems on Multiple Strings
Longest Substring Appearing in at Least Strings
Concatenate all strings using distinct unused separators, then run suffix array. Binary-search the length : for each contiguous group with
lcp >= l, check whether the group spans at least different source strings. . As before, two pointers + a monotonic deque bring this down to .
Life Forms
Longest Substring Appearing at Least Twice Non-Overlapping in Every String
Same concatenation trick, then binary-search . For each
lcp >= lgroup, per source string track the max and minrland check that every string has two occurrences that don’t overlap. .
PHRASES - Relevant Phrases of Annihilation
Longest Substring Appearing (or Reverse-Appearing) in Every String
For every string, append its reverse and use distinct unused separators between the pieces. Run suffix array on the combined string, then binary-search and check whether each group covers every original string. Also .