suffix array는 문자열 S의 N=length(S)개의 모든 접미사를 사전순으로 정렬한 배열로, O(N) 시간과 O(N) 메모리에 구할 수 있다. suffix array를 로그 시간에 구하는 방법을 안다면, 이해하기 어렵지 않을 것 같다.
길이 x의 문자열의 suffix array를 구하는 데 걸리는 시간을 SA(x)라고 하자.
일단 S에 있는 모든 문자보다 작은 문자 a를 잡아서 S 뒤에 3개 붙이고, Ti (0≤i≤N)를 S[i⋯i+2]로 정의하자.
일단 Ti들을 정렬해서 Ti가 각각 사전순으로 몇 번째인지 구하자. radix sort를 사용하면 O(N)에 정렬할 수 있다.
각각의 Ti를 하나의 문자로 보고 새로운 문자열 T=T1T4T7⋯T2T5T8⋯를 정의하자.
length(T)≤32N이므로, T의 suffix array를 구하는 데는 SA(32N)의 시간이 걸린다.
T의 suffix array를 이용하면, S[i⋯N−1] (i=3k)들을 모두 정렬할 수 있다.
이제 S[i⋯N−1] (i=3k)들을 모두 정렬하자. S[3i]=S[3j]라면 첫 글자 기준으로 정렬하면 된다. S[3i]=S[3j]라면 S[3i+1⋯N−1]의 사전순 순서를 알고 있으므로 그걸 이용해서 정렬하면 된다. radix sort를 사용하면 O(N)에 정렬할 수 있다.
마지막으로 정렬된 두 배열을 합치면 된다. 두 배열이 모두 정렬되어 있으므로 두 원소를 O(1)에 비교할 수 있다면 O(N)에 merge가 가능하다.
i, j가 mod 3으로 다르다면, k(≤2)가 존재하여 i+k, j+k가 모두 mod 3으로 0이 아니다. 따라서 앞의 2개 이하의 원소만 하나씩 비교하면, S[i+k⋯N−1], S[j+k⋯N−1]은 이미 정렬되어 있으므로 상수 시간에 바로 비교할 수 있다.
모든 시간을 합하면 SA(N)=SA(32N)+O(N)이고, 등비수열의 합이므로 SA(N)=O(N)이 된다.