오랜만에 플래티넘 문제 풀었다. 기분 좋다.
https://www.acmicpc.net/problem/4354
4354번: 문자열 제곱
알파벳 소문자로 이루어진 두 문자열 a와 b가 주어졌을 때, a*b는 두 문자열을 이어붙이는 것을 뜻한다. 예를 들어, a="abc", b="def"일 때, a*b="abcdef"이다. 이러한 이어 붙이는 것을 곱셈으로 생각한다
www.acmicpc.net

풀이
실패 함수를 활용해줘야 한다.
실패 함수를 통해 문자열이 얼마나 겹치는지 O(s1.size())동안 확인해줄 수 있다.
이를 바탕으로 sz(s1)/(sz(s1)-pr) 해당 식을 통해 최대 n을 구해줄 수 있는 것이다.
50%에서 틀렸습니다가 계속 나오는 경우 소수인 펠린드롬을 고려해줬는지 다시 한번 생각해보라.
다음은 반례이다.
ABABABA
.
Correct Output :
1
시간 복잡도 : O(T∗106)
아쉬운 점 : 문제를 처음 보고 실패 함수 쓰는 건가? 를 바로 캐치했지만 이를 구체화하는데까지 너무 오랜 시간이 걸렸다.
전체적인 감상 : 역시 어려운 문제 푸는게 기억에도 많이 남고 좋은 것 같다.
/* basic setup {{{ */ #include<bits/stdc++.h> #define ff first #define ss second #define pb push_back #define sz(x) ((int)x.size()) #define all(x) x.begin(),x.end() #define compress(x) sort(all(x)), x.erase(unique(all(x)), x.end()) #define fast_io ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0) using namespace std; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef const int ci; const int MOD = 1e9+7; const int INF = 0x3f3f3f3f; const ll LINF = 0x3f3f3f3f3f3f3f3f; /*}}}*/ vector<int> makeTable(string pattern){ int patternSize = pattern.size(); vector<int> table(patternSize, 0); int j = 0; for(int i=1;i<patternSize;i++){ while(j > 0 && pattern[i] != pattern[j]){ j = table[j-1]; } if(pattern[i] == pattern[j]){ table[i] = ++j; } } return table; } int main(){ fast_io; string s1; // T <= 10 // sz(s1) <= 1e6 // kmp 하듯이? while(cin>>s1){ if(s1 == ".") break; int pr = makeTable(s1).back(); if(sz(s1)%(sz(s1)-pr) != 0) cout<<1<<'\n'; else cout<<sz(s1)/(sz(s1)-pr)<<'\n'; } }
'백준 문제 해설' 카테고리의 다른 글
백준 7595 Triangles (0) | 2022.11.24 |
---|---|
백준 17267 상남자 (1) | 2022.11.23 |
백준 16234 인구 이동 (0) | 2022.11.22 |
백준 25386 라즈베리 파이 (0) | 2022.11.21 |
백준 25591 푸앙이와 종윤이 (0) | 2022.11.19 |
백준 25703 포인터 공부 (0) | 2022.11.18 |
백준 8558 Silnia (0) | 2022.11.17 |
백준 18398 HOMWRK (0) | 2022.11.16 |