문제 링크
- http://icpc.me/17233
사용 알고리즘
- KMP
- 투포인터
시간복잡도
- $O(\vert S \vert + \sum \vert P_i \vert + N\vert S \vert)$
풀이
$S$의 $i$번째 글자로 끝나는 부분 문자열 중, 문제의 조건을 만족하지 않는 가장 작은 시작점의 위치를 $f(i)$라고 합시다. (처음으로 만족하지 않는 시작점의 위치)
이때 $f(i) \leq f(i+1)$을 항상 만족합니다. 그러므로 투포인터를 활용하면 “$S[l..r]$이 문제의 조건을 만족하는지 판단하는 결정 문제”를 $O(\vert S \vert)$번 해결하는 것으로 문제를 해결할 수 있습니다.
KMP 알고리즘을 $N$번 돌려서(혹은 Aho-Corasick) $P_i$들이 $S$에서 등장하는 위치를 구합시다.
결정 문제를 해결하는 가장 간단한 방법은, 구간 $[l, r]$에 각 $P_i$가 등장하는지 이분 탐색으로 확인하는 것입니다. 이 방법은 결정 문제를 한 번 해결하는데 $O(N \log \vert S \vert)$가 걸리고, 총 $O(N \vert S \vert \log \vert S \vert)$만큼 걸립니다. 이 방법은 시간 초과를 받게 됩니다.
여기에서 log를 없애줄 수 있습니다. 결정 문제를 해결하는 순서를 생각해보면 $l, r$이 항상 단조 증가한다는 사실을 알 수 있습니다. 그러므로 $P_i$가 $S$에서 등장하는 위치를 deque로 관리하면서, 슬라이딩 윈도우 느낌으로 인덱스를 관리해줄 수 있습니다. 이 경우 결정 문제를 모두 해결하는데 $O(N \vert S \vert)$만큼 걸립니다.
KMP를 이용해 전처리를 하는데 $O(\vert S \vert + \sum \vert P_i \vert)$, 투포인터를 하는데 $O(N \vert S \vert)$이 걸리므로 시간 제한 내에 문제를 해결할 수 있습니다.
전체 코드
1 |
|