본문 바로가기
백준 문제 해설

백준 4354 문자열 제곱

by toomanysegtrees 2022. 11. 20.

오랜만에 플래티넘 문제 풀었다. 기분 좋다.

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 * 10^6)$

아쉬운 점 : 문제를 처음 보고 실패 함수 쓰는 건가? 를 바로 캐치했지만 이를 구체화하는데까지 너무 오랜 시간이 걸렸다.

전체적인 감상 : 역시 어려운 문제 푸는게 기억에도 많이 남고 좋은 것 같다.

/* 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