반응형
이 포스트에서는 프로그래밍 문제 사이트 백준 Online Judge의 13506번 : '카멜레온 부분 문자열' 문제의 풀이 코드와 해설을 다루고 있습니다.
문제 난이도는 Solved.ac 기준 Platinum 티어에 해당하며, 문제를 풀이하기 위해 KMP 알고리즘에 대한 이해가 필요합니다.
13506번 : 카멜레온 부분 문자열
입력받은 문자열의 접두사이면서 접미사이면서 문자열 중간에도 등장(이 때 세 위치가 모두 달라야 함)하는 가장 긴 문자열을 출력하는 문제입니다.
당연히 단순 브루트포스 탐색으로는 시간 제한을 통과하지 못하므로, KMP 알고리즘의 Pi 배열을 응용하여 해결하는 문제입니다.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> GetPi(string Pattern) {
vector<int> Pi(Pattern.length());
for(int i=1, j=0; i<Pattern.length(); i++) {
while(j>0 && Pattern[i] != Pattern[j]) j = Pi[j-1];
if(Pattern[i] == Pattern[j]) Pi[i] = ++j;
}
return Pi;
}
int main() {
string Str;
cin >> Str;
vector<int> Pi = GetPi(Str);
int L = Str.length(), Max = Pi[L-1];
while(Max > 0) {
for(int i=1; i<L-1; i++)
if(Pi[i] == Max) {
cout << Str.substr(0, Max);
return 0;
}
Max = Pi[Max-1];
}
cout << "-1";
}
Pi 배열을 응용하여 생각해보면 접두사 = 접미사인 위치는 Pi[L], Pi[Pi[L]], Pi[Pi[Pi[L]]], ...이므로 이를 활용하여 가운데에 등장하는 접두사 = 접미사 = 부분 문자열인 부분 문자열을 찾을 수 있습니다.
너무 간단히 설명하기에는 부족한 감이 있으니, 알고리즘이 작동하는 원리를 예제 입력 3인 "papapapap"를 이용하여 설명해두었습니다.
위의 그림을 참고하여 알고리즘의 작동 원리를 파악하시면 쉬울 것입니다.
반응형
'알고리즘 > 백준(BOJ) 문제풀이' 카테고리의 다른 글
[C++ 백준 풀이] 11377번 : 열혈강호 3, 11378번 : 열혈강호 4 (최대 유량 알고리즘) (0) | 2021.12.26 |
---|---|
[C++ 알고리즘] 최대 유량 알고리즘 (Network Flow, Ford-Fulkerson, Edmonds-Karp) (0) | 2021.12.26 |
[C++ 백준 풀이][Diamond II] 17441번 : 파리채 만들기 (그린 정리, Green's Theorem) (0) | 2021.12.25 |
[C++ 백준 풀이] 3356번 : 라디오 전송 / 3779번 : 주기 (KMP 응용) (0) | 2021.12.23 |
[C++ 백준 풀이] 16900번 : 이름 정하기 / 1305번 : 광고 / 1498번 : 주기문 (KMP 응용) (0) | 2021.12.23 |