문자열 매칭
주어진 문자열 S 안에 어떤 패턴문자열 P가 존재하는지, 몇개나 존재하는지, S의 몇번째 인덱스에 있는지 등등을 처리하는 매우 실용적인 문제
문자열 매칭을 위한 알고리즘들은 여러가지가 있다. len(S) = N, len(P) = M이라고 하자
나이브 매칭 O(NM)
노커멘트
라빈-카프 알고리즘 (Rabin-Karp Algorithm)
O(N+M)
해시 펑션을 이용하기 때문에, 해시 충돌로 오답이 나올 확률이 존재하기는 한다 (거의 없다)
KMP 알고리즘
O(N+M)
PS에서 사용되는 표준적인(?) 문자열 매칭 알고리즘.
Z 알고리즘
O(N+M)
Z 알고리즘으로도 선형시간에 문자열 매칭이 가능하긴 하다
Boyer–Moore string-search algorithm
최악 O(NM)
평균적으로는 KMP보다 빨라서 실용적으로는 더 선호되지만, 최악을 막는게 중요한 PS계열에서는 사용 불가
Two-way string-matching algorithm
최악 O(N+M)
KMP와 보이어무어를 잘 조합해서, 최악 경우에도 선형시간을 유지하도록 만들었다고 한다.
파이썬에 내장된 str.__contains__() 또는 str.find() 함수는 3.10 이후부터 Two-way string-matching algorithm 으로 구현되었다고 한다
stackoverflow 게시물
따라서 기본적으로는 다 필요없고.. 그냥 내장 함수를 쓰는것이 가장 빠르고 편리하다.
그냥 빠른 정도가 아니라, '압도적으로' 빠르다.
하지만, str.find()는, '첫번째' 매칭 위치만 알려준다는 제한이 있다. 오버래핑되는 '모든' 매칭의 위치를 찾기 위해서 str.find()를 반복해서 쓰는것은 O(N^2)이 되므로, 이 경우에는 알고리즘을 구현해야 한다.
구현할때는,
라빈-카프 알고리즘 (Rabin-Karp Algorithm)
,
KMP 알고리즘
,
Z 알고리즘
이 다 가능하지만, 일반적으로
KMP 알고리즘
이 그냥 제일 무난하고 빠르니까 이거를 쓰자.
세줄 요약
존재여부 또는 첫번째 매칭위치만 찾으면 된다면 그냥 내장 str 함수를 쓴다
리스트와 같이 문자열이 아닌 시퀀스에서 매칭을 해야 할 경우에도 가능하면 문자열로 변환해서 내장함수를 쓰자.
내장함수로 해결이 안될경우에는 KMP 알고리즘(teflib.string.find) 을 쓴다.
대표적으로, '모든' 매칭위치를 찾을때이다.