Rabin-Karp

라빈 카프 문자열 매칭
아스키 코드 기반의 해시 함수(Hash Function)을 이용하여 특정한 문자열에 대한 해시 값을 구한다
연속적인 문자열이 이어지는 상황이므로 해시 함수의 동작에 잇어서 연산 속도가 O(1)이다.

라빈 카프 문자열 매칭 알고리즘에서 해시 함수는 ‘각 문자의 아스키 코드 값에 2의 제곱 수를 차례대로 곱하여 더한 값’을 구한다
일반적으로 서로 다른 문자열의 경우 일반적으로 해시 값이 다름
하지만 충돌에 대한 처리가 필요하다
ex)
“abacdab”
= 97*2^6 + 98*2^5 + 97*2^4 + 99*2^3 + 100*2^2 + 97*2^1 + 98*2^0
= 12,380
해시 충돌을 감안해야 한다. 따라서 부분 문자열의 해시 값이 일치하는 경우에만 문자열을 재검사한다.
문자열이 이어져 있다는 특징을 이용하여 해시 값을 빠르게 계산할 수 있다.
다음 해시 값 = 2*(현재 해시 값 - 가장 앞에 있는 문자의 수치) + 새 문자의 수치
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *parent="acabacdabac";
char *pattern="abacdab";
void check(char* parent, char* pattern, int start){
int found=1;
int patternSize=strlen(pattern);
for(int i=0;i<patternSize;i++){
if(parent[start+i]!=pattern[i]){
found=0;
break;
}
}
if(found){
printf("[ %d ]\n", start+1);
}
}
void rabinKarp(char* parent, char* pattern){
int parentSize=strlen(parent);
int patternSize=strlen(pattern);
int parentHash=0, patternHash=0, power=1;
for(int i=0;i<=parentSize-patternSize;i++){
if(i==0){
for(int j=0;j<patternSize;j++){
parentHash=parentHash+parent[patternSize-1-j]*power;
patternHash=patternHash+pattern[patternSize-1-j]*power;
if(j<patternSize-1)power=power*2;
}
}
else{
parentHash=2*(parentHash-parent[i-1]*power)+parent[patternSize-1+i];
}
if(parentHash==patternHash){
check(parent, pattern, i);
}
}
}
int main(void){
rabinKarp(parent, pattern);
system("pasue");
return 0;
}
라빈 카프 문자열 매칭 알고리즘은 평균적으로 O(N+M)의 시간 복잡도를 가진다.
라빈 카프 알고리즘은 때에 따라서는 KMP 알고리즘보다 빠르게 동작하지만,
때에 따라서는 KMP 알고리즘보다 매우 느리게 동작할 수 있다.