내 속도 탄다. 이런 젠장
https://www.acmicpc.net/problem/11585
KMP 알고리즘을 사용하면 된다. 룰렛을 돌릴 문자열을 한번 더 더하면, 즉 원래 문자열이 S라면 S + S라고 하면 룰렛을 돌린 효과를 얻을 수 있다.
S + S에 대해 KMP 알고리즘을 적용하면 문제가 쉽게 풀린다.
단, S + S의 마지막을 POP 해줘야 한다. 안그러면 (예를 들어) ABC 라는 문자열이 들어왔을 때 ABCABC가 되어서
상근이가 고기를 먹을려면 나와야하는 ABC를 두 번이나 세게 된다.
그러니까 처음 상태에서 룰렛을 계속 돌리면 다시 처음 상태로 돌아올 텐데, 이 돌아온 상태까지 센다는 말이다.
/* 속타는 저녁 메뉴 */
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int Denominator, Numerator, N;
string Meat, Circle;
vector<int> Meat_get;
void get_meat();
void kmp();
void prime_factor();
int main(void) {
scanf("%d ", &N);
Denominator = N;
Meat.resize(N); Circle.resize(N);
for (int i = 0; i < N; i++)
scanf(" %c", &Meat[i]);
for (int i = 0; i < N; i++)
scanf(" %c", &Circle[i]);
Circle += Circle; Circle.pop_back();
get_meat();
kmp();
if (Numerator == Denominator + 1) {
cout << "1/1";
return 0;
}
prime_factor();
return 0;
}
void get_meat() {
Meat_get.resize(N);
for (int i = 1, j = 0; i < N; i++) {
while (j > 0 && Meat[i] != Meat[j])
j = Meat_get[j - 1];
if (Meat[i] == Meat[j])
Meat_get[i] = ++j;
}
}
void kmp() {
for (int i = 0, j = 0; i < (int)Circle.size(); i++) {
while (j > 0 && Meat[j] != Circle[i])
j = Meat_get[j - 1];
if (Meat[j] == Circle[i]) {
if (j == N - 1) {
Numerator++;
j = Meat_get[j];
}
else
j++;
}
}
}
void prime_factor() {
int a = Numerator, b = Denominator;
while (a != 0)
{
int t = b % a;
b = a;
a = t;
}
printf("%d/%d\n", Numerator / b, Denominator / b);
}
'알고리즘' 카테고리의 다른 글
[LeetCode] 13. Roman to Integer (0) | 2021.07.10 |
---|---|
백준(BOJ) 1765번 피자 굽기 자바(java) (0) | 2020.06.07 |
백준(BOJ) 1033번 칵테일 (0) | 2020.05.08 |
BOJ(백준) 2252 줄 세우기 (0) | 2020.03.04 |
백준(boj) 1030번 프랙탈 평면 (0) | 2020.03.03 |