KMP는 문자열 검색 시, 이미 비교했던 내용을 다시 비교하지 않도록 최적화된 알고리즘이다.
문자열을 탐색하면서 생기는 중복 비교를 피하기 위해 LPS 배열이라는 구조를 사용한다.
기존 브루트포스 방식은 문자열이 맞다가 틀리면 처음부터 다시 비교함 → 비효율적
KMP는 틀린 순간, "패턴의 어디부터 다시 비교하면 되는지"를 LPS 배열로 알려준다.
LPS[i]는 0부터 i까지의 부분 문자열에서,예시:
패턴 = "abab"
| 인덱스 | 부분 문자열 | LPS 값 | 설명 |
|---|---|---|---|
| 0 | a | 0 | 첫 글자라 없음 |
| 1 | ab | 0 | a ≠ b |
| 2 | aba | 1 | a == a |
| 3 | abab | 2 | ab == ab |
→ 최종 LPS 배열: [0, 0, 1, 2]
→ 시간복잡도가 항상 일정하고 안정적임
#include <stdio.h>
#include <string.h>
// LPS 배열을 만드는 함수
void computeLPSArray(char* pattern, int M, int* lps) {
int len = 0; // 이전까지 일치한 접두사/접미사 길이
lps[0] = 0; // 항상 0부터 시작
int i = 1;
while (i < M) {
if (pattern[i] == pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
// i는 증가 안 함
} else {
lps[i] = 0;
i++;
}
}
}
}
// KMP 매칭 함수
void KMPSearch(char* pattern, char* text) {
int M = strlen(pattern);
int N = strlen(text);
int lps[M];
computeLPSArray(pattern, M, lps);
int i = 0; // 텍스트 인덱스
int j = 0; // 패턴 인덱스
while (i < N) {
if (pattern[j] == text[i]) {
i++;
j++;
}
if (j == M) {
printf("패턴 발견 위치: %d\n", i - j);
j = lps[j - 1];
} else if (i < N && pattern[j] != text[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
}
int main() {
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
KMPSearch(pattern, text);
return 0;
}
패턴 발견 위치: 10
Ctrl + F 기능KMP는 단순히 알고리즘 대회용이 아니라,
실무에서도 성능 최적화와 직결되는 핵심 알고리즘이다.
구조는 단순하지만, 아이디어는 정말 강력하다.
“반복을 피하자” 이 철학이 담긴 알고리즘, 그게 바로 KMP다.