KMP 알고리즘
KMPKnuth-Morris-Pratt 알고리즘은 문자열 검색 알고리즘으로, 주어진 텍스트 내에서 특정 패턴을 효율적으로 찾기 위해 사용된다. 이 알고리즘은 문자 비교를 최소화하여 검색 속도를 향상시킨다.
브루트 포스법은 일치하지 않는 문자를 만나면 이전 단게에서 검사했던 결과를 버리코 패턴의 첫 문자부터 다시 검색을 수행하지만, KMP법은 검사했던 결과를 버리지 않고 효율적으로 활용하는 알고리즘이다.

주요 개념
- 부분 일치 테이블 (LPS 배열): 패턴의 접두사와 접미사가 일치하는 길이를 저장한다. 이를 통해 불필요한 비교를 줄일 수 있다.
- LPSLongest Prefix Suffix 배열은 주어진 패턴에서 접두사와 접미사가 일치하는 최대 길이를 저장한다. 이를 통해 패턴의 어느 부분까지 일치했는지를 기록하고, 불일치가 발생했을 때 패턴을 얼마나 이동해야 하는지를 결정한다.
LPS 배열 생성
- 현재 인덱스 i와 일치하는 문자가 있을 경우, j를 증가시켜 일치하는 길이를 업데이트하고 lps[i]에 저장한다.
- 일치하지 않을 경우, j를 LPS 배열을 참조하여 조정한다.
작동 원리
- LPS 배열 생성: 패턴을 순회하면서 각 위치에서의 LPS 값을 계산한다. 예를 들어, 패턴이 "ABABAC"이라면, LPS는 [0, 0, 1, 2, 0, 1]이 된다.
- 텍스트 검색: 텍스트를 순회하며 패턴과 비교한다. 만약 일치하지 않는 문자가 나타나면 LPS 배열을 참조하여 패턴을 이동시킨다. 이를 통해 불필요한 비교를 줄일 수 있다.
시간 복잡도
KMP 알고리즘의 최악의 경우 시간 복잡도는 O(N + M)이다.(여기서 N은 텍스트의 길이, M은 패턴의 길이다.) 그러나 보통의 경우, Worst-case에서도 O(N)이라고 알려져 있다. 다만 처리하기 복잡하고 패턴 안에 반복이 없으면 효율은 좋지 않다.
코드 구현
#include <stdio.h>
#include <string.h>
void computeLPSArray(char *pattern, int *lps, int M) {
int length = 0;
lps[0] = 0;
int i = 1;
while (i < M) {
if (pattern[i] == pattern[length]) {
length++;
lps[i] = length;
i++;
} else {
if (length != 0) {
length = lps[length - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
void KMPSearch(char *text, char *pattern) {
int M = strlen(pattern);
int N = strlen(text);
int lps[M];
computeLPSArray(pattern, lps, M);
int i = 0; // index for text
int j = 0; // index for pattern
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(text, pattern);
return 0;
}
보이어-무어법
보이어-무어법Boyer-Moore은 패턴 매칭 알고리즘으로, 패턴을 오른쪽 끝에서 왼쪽으로 비교한다. 이 알고리즘은 주로 두 가지 규칙(불일치 규칙과 좋은 접미사 규칙)을 사용하여 검색 과정을 최적화한다.
보이어-무어법은 이론이나 실제 효율 면에서 KMP법보다 뛰어난 알고리즘이다. 패턴의 끝 문자에서 시작해 앞쪽을 향해 검사를 수행한다. 이 과정에서 일치하지 않는 문자를 발견하면 미리 준비한 표를 바탕으로 패턴이 이동하는 값을 결정한다.

주요 개념
- 불일치 규칙: 현재 비교 중인 문자와 패턴의 문자가 일치하지 않을 경우, 패턴을 이동할 위치를 결정한다.
- 좋은 접미사 규칙: 패턴의 접미사가 텍스트의 해당 부분에서 일치할 경우, 패턴을 더 멀리 이동할 수 있다.
작동 원리
- 불일치 테이블 생성: 패턴의 각 문자가 텍스트에서 얼마나 멀리 이동할지를 기록하는 테이블을 만든다.
- 텍스트 검색: 텍스트를 순회하면서 패턴과 비교한다. 불일치가 발생하면 두 규칙을 사용하여 패턴을 이동한다. 이 과정에서 최대한 많은 문자를 건너뛰므로 검색 속도가 매우 빠르다.
시간 복잡도
보이어-무어법의 최악의 경우 시간 복잡도는 O(N)이나, 평균적인 경우에는 O(N/M)로 매우 효율적이다.
코드 구현
#include <stdio.h>
#include <string.h>
#define ALPHABET_SIZE 256
void badCharHeuristic(char *str, int size, int badchar[ALPHABET_SIZE]) {
for (int i = 0; i < ALPHABET_SIZE; i++) {
badchar[i] = -1;
}
for (int i = 0; i < size; i++) {
badchar[(int)str[i]] = i;
}
}
void BoyerMooreSearch(char *text, char *pattern) {
int m = strlen(pattern);
int n = strlen(text);
int badchar[ALPHABET_SIZE];
badCharHeuristic(pattern, m, badchar);
int s = 0; // shift of the pattern with respect to text
while (s <= (n - m)) {
int j = m - 1;
while (j >= 0 && pattern[j] == text[s + j]) {
j--;
}
if (j < 0) {
printf("패턴이 텍스트의 인덱스 %d에서 발견됨\n", s);
s += (s + m < n) ? m - badchar[text[s + m]] : 1;
} else {
s += max(1, j - badchar[text[s + j]]);
}
}
}
int main() {
char text[] = "ABABDABACDABABCABAB";
char pattern[] = "ABABCABAB";
BoyerMooreSearch(text, pattern);
return 0;
}
[참고자료]
KMP 알고리즘(Knuth-Morris-Pratt Algorithm)
KMP 알고리즘(Knuth-Morris-Pratt Algorithm) 문자열 검색 알고리즘의 하나로, 고지식한 알고리즘을 한 차례 개선할 수 있습니다. 찾을 단어의 접두사와 접미사를 이용하여 탐색횟수를 줄여줍니다. 우선,
j2wooooo.tistory.com
[알고리즘] KMP(Knuth-Morris-Pratt) 알고리즘
1. 개요 문자열 매칭을 생각해보면, ABABABAC // 원본 문자열 (S[i], 원본 문자열 길이 n) ABAC // 찾을 문자열 (P[i], 찾을 문자열 길이 m) 위의 S 문자열에서 P 문자열을 찾는 패턴 매칭에서 가장 단순(Naive)
pangtrue.tistory.com
KMP 알고리즘
1. KMP(Knuth-Morris-Pratt Alogorithm) 알고리즘이란?흔히 발견자 Knuth, Morris, Pratt의 앞글자를 딴 KMP로 읽히는 이 알고리즘은 전체 문자열에서 특정 문자열을 찾는 방식으로 오토마타(Finite-state automaton based
small-stepping.tistory.com
The Boyer Moore String Search Algorithm
An Algorithm that runs faster as the pattern length increases.
medium.com
Boyer-Moore 문자열 탐색 알고리즘
머리가 아닌 패턴의 꼬리 부분에서 일치하고 텍스트의 모든 단일 문자를 검색하는 대신 여러 문자의 점프에서 텍스트를 따라 건너 뛰는 것입니다. (Wikipedia)일반적인 상황에서 문자열은 앞부분
velog.io
'Krafton Jungle > 2. Keywords' 카테고리의 다른 글
| [WEEK06] 레드 블랙 트리 (Red-Black Tree) (0) | 2025.04.17 |
|---|---|
| [WEEK06] 균형 탐색 트리 (0) | 2025.04.16 |
| [WEEK05] B-Tree (0) | 2025.04.14 |
| [WEEK05] 포인터와 포인터 연산 (0) | 2025.04.11 |
| [WEEK05] malloc, calloc, realloc (0) | 2025.04.11 |