[알고리즘 소개]
전체 문자열에서 부분 문자열을 효율적으로 찾는 알고리즘.
[코딩 방법 - 실패 함수]
- 실패 테이블 만들기. table[i]는 0부터 i까지에서 접두사, 접미사가 겹치는 최대 길이
- 부분 문자열 pattern을 1부터 N까지 for문으로 순회, j는 0에서 시작
- j > 0 이거나 pattern[i] != pattern[j]이면 j = table[j - 1] 반복
(이전까지 계속 맞았다면 table[j - 1]에는 0이 아닌 값이 들어 있을 것이고 접미사 부분까지 맞았음이 확인됐으므로 처음부터 다시 비교할 필요가 없이 접미사와 같았던 접두사 부분까지는 생략하고 확인 가능) - pattern[i] == pattern[j] 이면 table[i] = ++j
[코딩 방법 - KMP]
- 전체 문자열 parent를 0부터 N까지 순회, pattern을 확인할 j도 0부터 시작
- j > 0이거나 parent[i] != pattern[j]이면 j = table[j - 1] 반복
(실패 테이블을 짜던 것과 같은 흐름. parent[i - 1]까지와 pattern[j - 1]까지 달랐다면 parent[i]와 pattern[0]을 비교하면 되는 것이고 같았다면 접미사 부분까지도 맞았으므로 접미사와 같은 접두사 생략) - pattern[i] == pattern[j] 이고 j < patternSIze - 1이라면 ++j
- pattern[i] == pattern[j] 이고 j == patternSIze - 1이라면 부분 문자열을 찾은 것.
[시간 복잡도]
$O(N + M)$
[참고]
왜 이렇게 해야하는지 이해가 안 간다면 아래 예시를 손으로 직접 해볼 것
- KMP: ABCABABCABCABABCD ABCABABCD
- 실패 함수: ABCABAABCABC
[공부용 링크]
'정리 > 알고리즘' 카테고리의 다른 글
[알고리즘] 쾨닉의 정리 (Kőnig's theorem) (0) | 2023.02.27 |
---|---|
[알고리즘] 마나허 (Manacher) (0) | 2023.02.26 |
[알고리즘] 이분 탐색 (Binary Search) (0) | 2023.01.15 |
[알고리즘] 크루스칼 (Kruskal) (0) | 2021.04.05 |
[알고리즘] 뤼카의 정리 (Lucas' Theorem) (2) | 2021.03.27 |