DSA Notes
Master suffix arrays — what a suffix array is, how to build it using simple and O(n log n) algorithms, the LCP (Longest Common Prefix) array, how to use suffix arrays for pattern searching in O(m log n), finding the longest repeated substring, and counting distinct substrings.
What Is a Suffix Array?
A suffix array is a sorted array of all suffixes of a string. Given a string S, its suffix array SA stores the starting indices of all suffixes of S in lexicographically sorted order.
| Index 0 | "banana" |
| Index 1 | "anana" |
| Index 2 | "nana" |
| Index 3 | "ana" |
| Index 4 | "na" |
| Index 5 | "a" |
| "a" | index 5 |
| "ana" | index 3 |
| "anana" | index 1 |
| "banana" | index 0 |
| "na" | index 4 |
| "nana" | index 2 |
The suffix array is compact (only indices, not actual strings) and enables O(m log n) pattern matching where a full suffix tree would use O(n) space but be harder to build.
O(n log n) Construction — Prefix Doubling
The efficient approach uses prefix doubling (Manber-Myers algorithm):
LCP Array (Longest Common Prefix)
The LCP array stores the length of the longest common prefix between consecutive suffixes in the sorted suffix array.
| SA[0]=5 | "a" |
| SA[1]=3 | "ana" LCP with prev = 1 ("a") |
| SA[2]=1 | "anana" LCP with prev = 3 ("ana") |
| SA[3]=0 | "banana" LCP with prev = 0 |
| SA[4]=4 | "na" LCP with prev = 0 |
| SA[5]=2 | "nana" LCP with prev = 2 ("na") |
Pattern Searching in O(m log n)
With a suffix array, binary search finds all occurrences of pattern P in string S:
Compare with KMP: Both O(n + m) for single search, but suffix array enables O(m log n) for multiple pattern searches without preprocessing each pattern separately.
Longest Repeated Substring
The longest repeated substring is found by looking at the maximum value in the LCP array.
Count Distinct Substrings
Total substrings of length-n string = n*(n+1)/2. Duplicate substrings are counted by the LCP array.
def count_distinct_substrings(s: str) -> int:
"""
Count distinct non-empty substrings.
Total substrings - duplicates (counted by LCP array).
"""
n = len(s)
sa = build_suffix_array(s)
lcp = build_lcp_array(s, sa)
total = n * (n + 1) // 2 # All substrings
duplicates = sum(lcp) # LCP values count duplicates
return total - duplicates
print(count_distinct_substrings("aaa")) # 3 — "a","aa","aaa"
print(count_distinct_substrings("abab")) # 7 — "a","b","ab","ba","aba","bab","abab"
print(count_distinct_substrings("abcde")) # 15 — all 5*6/2 are distinctSuffix Array vs Suffix Tree
| Feature | Suffix Array | Suffix Tree |
|---|---|---|
| Space | O(n) — compact | O(n) — but large constant factor |
| Construction | O(n log n) simple | O(n) but very complex |
| Pattern search | O(m log n) | O(m) |
| Implementation | Manageable | Very complex |
| LCP queries | O(1) with sparse table | O(1) native |
| Practice | Widely used in competitive programming | Rare in practice |
In competitive programming: Suffix arrays with LCP arrays are the standard. Suffix trees are almost never implemented from scratch.
Summary
A suffix array is the sorted array of all suffix starting indices of a string.
- Construction: O(n² log n) naive, O(n log n) with prefix doubling
- LCP array: O(n) via Kasai's algorithm
- Pattern search: O(m log n) via binary search
- Longest repeated substring: Maximum value in LCP array
- Distinct substrings: n(n+1)/2 - sum(LCP)
Applications: DNA sequence analysis, data compression (BWT/bzip2), plagiarism detection, bioinformatics, full-text search engines.
*Next: Skip List*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Suffix Array — Construction, LCP Array, and String Search Applications.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, advanced, topics, suffix
Related Data Structures & Algorithms Topics