-
백준 1786번 찾기 (boj/1786.c)R&E: research & education/PS 2024. 1. 18. 19:25
KMP 알고리즘 문제입니다.
#include <stdio.h> #include <string.h> #define MAX_N 1000002 char T[MAX_N] = { 0, }; char P[MAX_N] = { 0, }; int pi[MAX_N] = { 0, }; int res[MAX_N]; int main(void){ int lenT, lenP; int cur, loc, cnt; fgets(T, MAX_N, stdin); fgets(P, MAX_N, stdin); lenT=strlen(T); lenP=strlen(P); lenT--; lenP--; T[lenT]=P[lenP]=0; pi[0] = -1; for(int i=1;i<lenP;i++){ pi[i]=-1; for(cur=i-1;cur!=-1;cur=pi[cur]){ if(P[i] == P[pi[cur]+1]){ pi[i]=pi[cur]+1; break; } } } loc=-1; cnt=0; for(cur=0;cur<lenT;cur++){ if(loc == -1){ if(T[cur] == P[0]){ loc=cur; } else{ continue; } } if(T[cur] == P[cur-loc]){ if(cur-loc==lenP-1){ res[cnt++] = loc+1; loc = (pi[cur-loc]!=-1)?cur-pi[cur-loc]:-1; } else{ continue; } } else{ loc = (pi[cur-1-loc]!=-1)?(cur-1)-pi[cur-1-loc]:-1; cur--; } } printf("%d\n", cnt); for(int i=0;i<cnt;i++){ printf("%d ", res[i]); } return 0; }
이 알고리즘은 작성할 시 주의할 점이 몇 가지 있습니다.
- line 18: pi[idx]값이 항상 pi[idx-1]+1 또는 -1이 아니다. 즉, if(string[idx] == string[pi[idx-1]+1]) 에서 false가 뜨면 pi[idx-1]에서 재판단을 해줘야 한다. 당연히 시간복잡도는 O(M)이 아니다.
- line 24: loc==-1인 상황에서, T[cur]=P[0]이 떳을 때 바로 continue를 때리면 안 됩니다. P의 길이가 1인 상황을 고려해야 하기 때문. 이 경우에는 loc==cur이 성립하기 때문에 line31의 if문에 들어가면 아웃바운드가 뜬다고 할 수 있는데, 조건에 따라 T[cur]==P[cur-loc]가 항상 성립할 것이기 때문에 아웃바운드는 뜨지 않습니다.
- line 31: 만약, pi값이 -1이더라고, 현재 위치에서 재탐색을 한 번 해줘야 합니다. T=kaafg P=afg인 경우를 위해서입니다.
'R&E: research & education > PS' 카테고리의 다른 글
백준 6987번 월드컵 (boj/6987.c) (0) 2024.01.23 백준 1310번 달리기 코스 (boj/1310.cpp) (1) 2024.01.22 백준 13977번 이항 계수와 쿼리 (boj/13977.c) (1) 2024.01.21 백준 3015번 오아시스 재결합 (boj/3015.c) (0) 2024.01.15 백준 2618번 경찰차 (boj/2618.c) (0) 2024.01.14