Search
Duplicate
😀

06. 문자열 알고리즘

태그
트리
이진 트리
트리 탐색

라빈-카프 알고리즘

문자열 검색을 위해 해시 값 함수를 이용
패턴 내의 문자열을 일일이 비교하는 대신에 패턴의 해시 값과 본문 안에 있는 하위 문자열의 해시값만을 비교
최악의 시간 복잡도는 O(MN)이지만 평균적으로는 선형에 가까운 빠른 속도를 가지는 알고리즘

찾고자 하는 문자열에서 해쉬값을 구할 때

찾고자 하는 문자열에서 한글자씩 이동하며 패턴 길이만큼 읽어서 해쉬 값을 계산하는 것이 아니라
새로 추가되는 문자와 그 전에 읽었던 값을 이용하여 해쉬값을 구한다.
즉 아래 그림처럼 다음 해쉬값을 구할 때 그 전의 해쉬값을 이용한다.

고려사항

처음 해쉬 값을 구할 때는 찾고자 하는 문자열에서 패턴 길이 만큼 읽어서 구한다.
본 예제에서는 이해를 돕기 위해 패턴의 길이를 4자리 정수로 작게 했지만 패턴이 문자열이며 길이가 커지면 일정 자리수로 맞추기 위해 mod 연산을 취해준다(해쉬)
따라서 해쉬 값이 일치하더라도 실제 패턴이 일치하지 않을 수 있기 때문에 해쉬 값이 일치하면 문자열 일치를 검사해야 한다(해쉬 충돌)

보이어 무어 알고리즘

오른쪽에서 왼쪽으로 비교하는 알고리즘
보이어-무어 알고리즘은 패턴에 오른쪽 끝에 있는 문자가 불일치 하고 이 문자가 패턴 내에 존재하지 않는 경우, 이동 거리는 무려 패턴의 길이 만큼이 된다.
최악의 시간 복잡도는 O(MN)이지만 최선의 시간 복잡도는 O(N/M)이며 평균적으로는 가장 빠른 속도를 가지는 알고리즘

Case - 오른쪽 끝에 있는 문자가 불일치 하고 이 문자가 패턴 내에 존재하는 경우

실제로는 패턴의 포인터가 움직이는 것이 아닌 T[] 배열의 포인터가 이동하는 것!

skip 배열 만들기

skip[ ch ] : 본문 ch 문자에서 패턴 불일치가 발생했을 때 본문 포인터의 skip 횟수를 저장
패턴에 포함되지 않은 문자들은 본문 포인터가 패턴 길이만큼 skip 해야하므로 패턴의 길이가 곧 skip 배열의 값이 됨
패턴 문자들의 skip 배열 값(패턴 마지막 문자는 제외)
(패턴 문자열의 길이 - 1) - 각 패턴 문자의 인덱스
ex) rithm의 skip 배열
만약 중복되는 문자 (ritthm 처럼)가 있으면 제일 뒤쪽 기준으로 맞춘다.

KMP(Knuth-Morris-Pratt) 알고리즘

불일치가 발생한 텍스트 문자열의 앞 부분에 어떤 문자가 있는지를 미리 알고 있으므로, 불일치가 발생한 앞부분에 대하여 다시 비교하지 않고 매칭을 수행
보이어 무어 알고리즘과 다르게 원본 문자열이 아닌 패턴 문자열의 포인터를 바꿈!
패턴을 전처리하여 부분일치 테이블 배열 pi[k]을 구해서 잘못된 시작을 최소화함
pi[k] : 처음부터 k 인덱스까지를 끝으로 하는 부분 문자열에서 일치하는 접두사와 접미사가 일치하는 최대 길이
시간 복잡도 : O(M+N)

KMP 동작

텍스트에서 abcdabc까지는 매치되고, e에서 실패한 상황
맨 앞의 abc와 실패 직전의 abc는 동일함을 이용할 수 있다.
실패한 텍스트 문자와 P[4]를 비교한다.

패턴을 이용한 부분일치 테이블 만들기

매칭이 실패했을 때 패턴 포인터가 돌아갈 곳을 계산