본문 바로가기

algorithm

KMP

KMP는 주어진 문자열의 부분 문자열 중에서 비교 문자열과 매칭이 되는지 확인하는 알고리즘으로, 문자열 검색 알고리즘 중 하나입니다.

완전탐색의 방식으로는 두 문자열의 처음부터 끝까지 비교했다면,

KMP는 이미 아는 정보를 이용해서 덜(?) 비교 합니다.

구체적으로 어떻게 하는 것일까요?

실패함수라는 것을 이용합니다.

실패함수는 매칭에 실패했을 때, 비교를 생략할 수 있는 범위를 알려주는 함수입니다.

 

설명을 위해 백준 1786번 문제를 인용하겠습니다.


T라는 문자열과, P라는 문자열이 다음과 같을 때, 첫번째 비교는 다음과 같습니다.

      1 2 3 4 5 6 7 8 9 …
T : [ A B C D A B C D A B D E ]     
       |  |  |  |  |  |  X
P : [ A B C D A B D ]      
      1 2 3 4 5 6 7

C와 D가 일치하지 않으므로 T가 1일 때는 매칭에 실패했습니다. 하지만, 그전까지는 문자가 일치했으므로, P의 2번째 문자(C)부터 매칭을 확인하면 됩니다.

    1 2 3 4 5 6 7 8 9 …
T : [ A B C D A B C D A B D E ]     
                 *  *   |  |  |  |  |                                                                 ( * : 매칭이 된다는 것을 알고 있음) 
P :            [ A B C D A B D ]      
                  

따라서, O(NM)이 아닌 O(N+M)의 시간복잡도로 문제를 해결 할 수 있게 되는 것입니다.

 

실패함수의 구현은 다음과 같습니다(코드 출처:위키백과)

pi[i] : i번째에서 매칭에 실패했을 때, 다음 비교를 어디부터 해야 할지 알려주는 함수

vector<int> KMP_GET(string grope){
    int Begin=0, Length = (int)grope.size();
    vector<int> pi(Length, 0);
    for(int i=1 ; i< Length ; i++){
        while(grope[i] != grope[Begin] && Begin > 0)Begin = pi[Begin-1];
        if(grope[i] == grope[Begin]) pi[i] = ++Begin;
    }
    return pi;
}

 

GROPE(ABCDABD) PI
A 0
B 0
C 0
D 0
A 1
B 2
D 0

 

'algorithm' 카테고리의 다른 글

1377 버블소트  (0) 2022.03.22
dp-우수마을  (0) 2022.03.07
공항,암호코드  (0) 2022.02.16
곱셈, 이분탐색  (0) 2022.02.02
2075 - N번째 큰 수  (0) 2022.01.30