2 분 소요

KMP 알고리즘의 다른 구현

  • 코드 20.2 의 KMP 알고리즘은 전통적인 KMP 알고리즘 구현과는 약간 다름
  • 전통적인 구현은 이해하기 어렵지만 간결하고 다른 알고리즘에 응용되기 쉬움

코드

vector<int> kmpSearch2(const string &H, const string &N)
{
        int n = H.size(), m = N.size();
        vector<int> result;
        vector<int> pi = getPartialMatch(N);

        //현재 대응된 글자의 수
        int matched = 0;
        //짚더미의 각 글자를 순회
        for (int i = 0; i < n; i++)
        {
                 //matched번 글자와 짚더미의 해당 글자가 불일치할 경우,
                 //현재 대응된 글자의 수를 pi[matched-1]로 줄인다
                 while (matched > 0 && H[i] != N[matched])
                         matched = pi[matched - 1];

                 //글자가 대응될 경우
                 if (H[i] == N[matched])
                 {
                         matched++;
                         if (matched == m)
                         {
                                 result.push_back(i - m + 1);
                                 matched = pi[matched - 1];
                         }
                 }
        }
        return result;
}
  • 지금까지 대응된 문자의 수 matched 만을 유지하면서 짚더미의 모든 글자를 순회
  • 각 글자마다 matched 를 적절하게 갱신
  • 마지막에 본 짚더미의 글자 번호 i 는 20.2 코드의 begin + matched 와 같기에

두 코드는 완전히 같은 알고리즘을 구현

H=aabaaba

n=7

N=abaab

m=5

i matched H[i] ≠ N[matched] matched > 0 matched pi[matched - 1] matched H[i] == N[matched] matched matched == m ret.put_back(i-m+1) matched
0 0 a = a, False False       a = a, True 1 1 ≠ 5    
1 1 a = b, True True 1 pi[0] 0 H[1] == N[0]        
a = a, True 1 1 ≠ 5                  
2 1 b = b, False         H[2] == N[1] 2 2 ≠ 5    
3 2 a = a, False         H[3] == N[2]        
a = a 3 3 ≠ 5                  
4 3 a = a, False         H[4] == N[3]        
a == a 4 4 ≠ 5                  
5 4 b = b, False         H[5] == N[4]        
b == b 5 5 = 5, True 5 - 5 + 1 = 1                
ret.put_back(1) pi[5-1]                    
(abaab)→ 2                      
5 2                    
                       

###