티스토리 뷰
KMP 알고리즘으로 대표적인 문자열(String) 매칭 알고리즘입니다. 문자열 매칭 알고리즘이란 특정한 글이 있을 때 그 글 안에서 하나의 문자열을 찾는 알고리즘입니다.
KMP 알고리즘은 접두사와 접미사의 개념을 활용하여 '반복되는 연산을 얼마나 줄일 수 있는지'를 판별하여 매칭할 문자열을 빠르게 점프하는 기법입니다.
우리가 구해야 할 것은 위와 같이 접두사와 접미사가 일치하는 최대 길이입니다.
길이 | 문자열 | 최대 일치 길이 |
1 | a | 0 |
2 | ab | 0 |
3 | aba | 1 |
4 | abac | 0 |
5 | abaca | 1 |
6 | abacaa | 1 |
7 | abacaab | 2 |
8 | abacaaba | 3 |
위와 같이 접두사와 접미사를 구하게 되면 접두사와 접미사가 일치하는 경우에 한해서는 점프(Jump)를 수행할 수 있다는 점에서 몹시 효율적입니다. 이제 위와 같은 접두사와 접미사의 최대 일치 길이는 어떻게 구할 수 있을지 알아봅시다.
// 일치했던 부분까지 되돌아가서 다시검사를 하는 방식으로 빠르게
// '최대 일치 길이'테이블을 구축할 수 있습니다.
vector<int> makeTable(string pattern) {
int patternSize = pattern.size();
vector<int> table(patternSize, 0);
int j = 0;
for(int i = 1; i < patternSize; i++) {
while(j > 0 && pattern[i] != pattern[j]) {
j = table[j - 1];
}
if(pattern[i] == pattern[j]) {
table[i] = ++j;
}
}
return table;
}
int main(void) {
string parent = "ababacabacaabacaaba";
string pattern = "abacaaba";
vector<int> table = makeTable(pattern);
for(int i = 0; i < table.size(); i++) {
cout << table[i] << " ";
}
cout << endl;
}
KMP 알고리즘이 문자열을 찾는 과정
#include <iostream>
#include <vector>
using namespace std;
// 일치했던 부분까지 되돌아가서 다시검사를 하는 방식으로 빠르게
// '최대 일치 길이'테이블을 구축할 수 있습니다.
vector<int> makeTable(string pattern) {
int patternSize = pattern.size();
vector<int> table(patternSize, 0);
int j = 0;
for(int i = 1; i < patternSize; i++) {
while(j > 0 && pattern[i] != pattern[j]) {
j = table[j - 1];
}
if(pattern[i] == pattern[j]) {
table[i] = ++j;
}
}
return table;
}
void KMP(string parent, string pattern) {
vector<int> table = makeTable(pattern);
int parentSize = parent.size();
int patternSize = pattern.size();
int j = 0;
for(int i = 0; i < parentSize; i++) {
while(j > 0 && parent[i] != pattern[j]) {
j = table[j - 1];
}
if(parent[i] == pattern[j]) {
if(j == patternSize - 1) {
printf("%d번째에서 찾았습니다.\n", i - patternSize + 2);
j = table[j];
}
else {
j++;
}
}
}
}
int main(void) {
string parent = "ababacabacaabacaaba";
string pattern = "abacaaba";
vector<int> table = makeTable(pattern);
for(int i = 0; i < table.size(); i++) {
cout << table[i] << " ";
}
cout << endl;
KMP(parent, pattern);
}
'Algorithm > Algorithm' 카테고리의 다른 글
라빈-카프(Rabin-Karp) 알고리즘 (0) | 2020.07.29 |
---|---|
이분 매칭(Bipartite Matching) (0) | 2020.07.26 |
네트워크 플로우(Network Flow) (0) | 2020.07.26 |
강한 결합 요소 (Strongly Connected Component) (0) | 2020.07.25 |
위상 정렬 알고리즘(Topology Sort) (0) | 2020.07.25 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- timecomplexity
- 파이썬
- 배열
- 비트필드
- 자료구조
- Algorithm
- 2차원 배열
- 공간복잡도
- 형승격
- 회전리스트
- 강의
- 간접 지정
- 직접 지정
- codeit
- inflearn
- 구조체
- 종류
- 시간복잡도
- 프로그래밍
- 공부
- 포인터
- 공용체
- C
- 1차원 배열
- call by reference
- call by value
- 알고리즘
- 3차원 배열
- 다차원 배열
- 재귀함수
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함