728x90
접미사 배열을 n * lg(n) ^ 2 시간으로 찾게 해주는 알고리즘인데 간단히 소개하면
t = 1, 2, 4, 8 .... 2^n - 1 순으로 증가하며 이 t번째 문자를 기준으로 접미사를 정렬해 나가는 것이다.
struct MM_Comparator {
const vector<int>& group;
int t;
MM_Comparator(const vector<int>& _group, int _t) : group(_group), t(_t) {}
bool operator() (int a, int b) {
if (group[a] != group[b]) return group[a] < group[b];
return group[a + t] < group[b + t];
}
};
vector<int> MamberMiaus(const string& s) {
int n = s.size();
int t = 1;
vector<int> group(n + 1);
for (int i = 0; i < n; ++i) group[i] = s[i]; // 첫번째 글자를 기준으로 정렬
group[n] = -1; // t 길이의 글자를 그룹에 배정하기 위한 임시값
vector<int> perm(n);
for (int i = 0; i < n; ++i) perm[i] = i; // 접미사 배열의 순번 저장
while (t < n) {
MM_Comparator compareUsing2T(group, t);
sort(perm.begin(), perm.end(), compareUsing2T);
t *= 2;
if (t >= n) break;
vector<int> newGroup(n + 1);
newGroup[perm[0]] = 0;
newGroup[n] = -1;
for (int i = 1; i < n; ++i)
{
if (compareUsing2T(perm[i - 1], perm[i]))
newGroup[perm[i]] = newGroup[perm[i - 1]] + 1;
else
newGroup[perm[i]] = newGroup[perm[i - 1]];
}
group = newGroup;
}
return perm;
}
다른 블로그를 보면 정리가 잘 되어있지만 왜 2의 지수승으로 비교를 해나가도 문제가 해결되는지 알아내는데 상당한 시간이 걸려서 까먹기 전에 정리해 본다
1. t = 1일때 기준으로 정렬이 된다면 반드시 길이가 1일 접미사는 독립적인 그룹으로 들어가 있다
2. t = 2일때 기준으로 정렬이 된다면 길이가 2일 접미사 는 독립적인 그룹이며 3일 접미사도 1일 접미사가 이미 독립적인 그룹수를 가지고 있으므로 독립적입 그룹에 배정된다 즉 이 때 반드시 1, 2, 3은 독립적인 그룹에 들어가 있다
3. t = 4일때 4일 접미사는 독립적인 그룹이며 1, 2 ,3 이 독립적인 그룹이므로 5, 6, 7 그룹도 독립적인 그룹에 배정된다
4. t = n일때 n은 독립적인 그룹이며 n - 1 이 이미 독립적인 그룹이므로 n * 2 - 1그룹도 독립적인 그룹에 배정된다.
이 동작의 원리로 인하여 이 알고리즘이 동작하게 된다고 생각하는데 논문은 읽어보지 않아서 확실하다고는 정확하지 않을수도 있다
728x90
'알고리즘문제 풀어보기' 카테고리의 다른 글
프로그래머스 - 타겟넘버 <알고리즘 비트연산 계산> (0) | 2024.04.27 |
---|---|
C# - 프로그래머스 바탕화면정리 - 문자열 문제 (0) | 2024.03.26 |
c# - Sort할때 실수하는 상황 <Sort>안됨 (0) | 2024.02.20 |
C# 알고리즘 - Combination (0) | 2024.02.19 |
문제풀때 생각해야 할 사항들 (0) | 2023.01.12 |