본문 바로가기
Algorithm/알고리즘 공부노트

12. String Match(KPM, Rabin-Karp, Palindrome)

by devraphy 2021. 10. 20.

0. 시작하기전에

- 한동안 알고리즘 공부를 하며 깨달은게 있다.

- 알고리즘을 얼마나 외우고 있느냐는 코딩테스트에서는 중요하지 않다는 점이다. 

- 결국 이론적인 이해도와 지식에 대한 소화시간을 충분히 갖고, 이를 기반으로 응용적인 사고가 가능하냐는 부분이 가장 중요하다.

- 그러므로 코드를 외우려 노력하지말고, 그 안의 규칙성과 논리를 이해하기 위해 더 시간을 투자하기를 바란다. 


1. String Match

- 문자열을 탐색하는 방법론이다.

- 대표적으로 KMP 알고리즘과 Rolling Hash를 사용하여 구현한 Rabin Karp 알고리즘이 있다.

- 일반적으로 String Match 알고리즘은 O(n)의 시간복잡도를 갖는다.

 

a) 시간복잡도

- 문자열 탐색은 다음과 같은 과정을 거친다. 

string1 = ["abc", "abd", "abk"] # 원래는 "abcabdabk" 이다. 
sub_string = "abk"

- 위의 예시처럼 string1에서 sub_string과 동일한 부분이 있는지를 찾게된다.

- string1에서 sub_string을 찾기 위해서는 문자열의 각 문자를 탐색하면서 동일한 문자열의 index를 찾게된다. 

- string1의 길이가 n이고 sub_string의 길이가 m일 때, 해당 sub_string을 찾는데 걸리는 시간복잡도는 O(n)이 된다. 


2. KMP 알고리즘

- string과 sub_string 각각에 포인터를 생성하여 각 문자를 비교하는 알고리즘이다. 

- 다음 예시를 통해 이해해보자. 

 

a) 2개의 포인터를 만들어 글자를 비교한다.

- 각 문자열마다 포인터를 생성하여 각 문자를 비교한다.

- 글자가 같은 경우, 2개의 포인터 모두 한칸씩 이동한다.

- 글자가 다른 경우, string의 포인터를 한칸 이동한다.

 

- 예시 2번의 경우, O(n * m)의 시간복잡도를 갖는다. sub_string에서 a가 반복되는 구간이 있기 때문이다. 

- 즉, String의 포인터를 한칸 이동할 때마다, sub_string의 길이만큼 비교연산은 하게 되는 것이다. 

- 그러면 이 문제는 어떻게 해결할 수 있을까? 

- 간단하다. 반복되는 부분보다 반복되지 않는 부분을 우선적으로 탐색하면 된다. 

- 이러한 이유로 KMP 알고리즘이 발명되었다. 

 

b) 반복되는 패턴을 찾는 방법

- sub_string을 구성하는 문자의 반복횟수를 확인하여 패턴을 확인하는 방법을 사용한다. 

- 다음과 예시를 살펴보자.

 

c) 예시1 - 패턴을 이용한 문자열 Matching 

 

c) 예시2 - 패턴을 이용한 문자열 Matching 

- 이처럼, 최종적으로 matching 되는 문자열을 찾게 된다.

- 반복되는 문자열에 대한 패턴정보를 기반으로 matching 문자열을 찾는 방식을 KMP 알고리즘이라고 한다.

- 반복되는 문자열에 대한 탐색을 하지 않으므로, KMP 알고리즘은 O(n)의 시간복잡도를 갖는다. 

 


3. Rabin Karp 알고리즘(feat. Rolling Hash)

* Rolling Hash라는 이름처럼, 기본적으로 Hash 또는 Hash 테이블에 대한 이해를 필요로 한다.

- 우선 sub_string의 길이(5)와 hash 값(42)을 구한다.

- sub_string의 길이만큼 string의 문자들을 묶어서 hash 값을 구한다. 

- 즉, sub_string의 hash 값과 동일한 hash 값을 가진 string의 문자열을 찾는 방식이다.

 

 

a) window sliding을 통한 탐색 

 

b) 예시2

 

- 이처럼 sub_string의 길이만큼 string을 나누고, 나누어진 문자열의 hash값과 sub_string의 hash값을 비교한다.

- 동일한 hash 값을 가진 문자열을 찾는다면, 각 문자를 비교하여 한번 더 확인한다. 

- 단순히 hash값을 이용하여 문자열을 탐색하는 것으로, O(n)의 시간복잡도를 갖는다. 

- 이와 같은 방식이 Rolling hash를 이용한 Rabin Karp 알고리즘이다. 

 

* 만약 면접이나 코딩테스트에서 String Match문제가 나온다면, KMP보다 Hash를 이용한 Rabin Karp 알고리즘을 추천한다.


3. Palindrome

 

'Algorithm > 알고리즘 공부노트' 카테고리의 다른 글

Return에 대하여  (0) 2021.11.28
파이썬 클래스와 self의 의미  (0) 2021.11.06
11. Array(배열) - Radix Sort  (0) 2021.10.08
10. Array(배열) - Counting Sort  (0) 2021.10.05
9. Array(배열) - Heap Sort(2)  (0) 2021.09.09

댓글