문제 정보
- 문제: https://www.acmicpc.net/problem/4354
- 요약: 알파벳 소문자로 이루어진 문자열 s가 주어질 때, s = a^n을 만족하는 가장 큰 n을 찾는 프로그램을 작성합니다. 예를 들어 “ababab” = “ab”^3이므로 답은 3입니다.
- 제한: 문자열 길이는 1 이상 1,000,000 이하, 10개 이하의 테스트 케이스, 마지막 입력은 마침표(".")
입출력 형식/예제
| |
예제 설명:
- “abcd”: 모든 문자가 다르므로 “abcd”^1만 가능 → 1
- “aaaa”: “a”^4 → 4
- “ababab”: “ab”^3 → 3
접근 개요(아이디어 스케치)
- 핵심 관찰: 문자열 s = a^n이려면 a의 길이는 len(s)의 약수여야 합니다.
- KMP 활용: KMP failure function의 마지막 값을 이용하면 최소 주기(period)를 O(n)에 구할 수 있습니다.
- 주기 판정: len - failure[len-1] = period일 때, len % period == 0이면 s = a^(len/period)입니다.
- 효율성: 모든 약수를 검사하는 것보다 KMP failure function을 활용하는 것이 더 빠릅니다.
알고리즘 설계
KMP Failure Function을 이용한 주기 찾기
Failure Function 구성:
- failure[i] = s[0..i]에서 prefix와 suffix가 일치하는 최대 길이
- 예: “ababab"의 failure = [0,0,1,2,3,4]
주기 계산:
- period = len - failure[len-1]
- len이 period로 나누어떨어지면 s = a^(len/period)
정확성 근거:
- failure[len-1] = k는 s[0..k-1] == s[len-k..len-1]을 의미합니다.
- 이는 문자열의 처음 k개 문자와 마지막 k개 문자가 같다는 뜻입니다.
- 따라서 period = len - k가 주기가 될 수 있는 최소값입니다.
- len % period == 0이면 문자열이 완벽하게 주기적입니다.
복잡도
- 시간: O(n), KMP failure function 구성이 선형 시간
- 공간: O(n), failure function 배열 저장
구현 (C++)
| |
코드 설명
입력 처리:
- 문자열을 읽고, “.“일 때까지 반복 처리합니다.
- cin » s로 공백 없는 문자열을 입력받습니다.
Failure Function 구성:
- failure[i]는 s[0..i]에서 prefix와 suffix가 일치하는 최대 길이입니다.
- KMP 패턴 매칭 알고리즘의 전처리 단계와 동일합니다.
주기 계산:
- period = len - failure[len-1]로 최소 주기를 구합니다.
- 예: “ababab"에서 len=6, failure[5]=4이므로 period=2
답 출력:
- len % period == 0이면 n = len / period
- 아니면 n = 1 (문자열 자신의 1제곱만 가능)
코너 케이스 체크리스트
- 길이 1인 문자열 (예: “a”) → 1 출력
- 모든 문자가 같은 경우 (예: “aaaa”) → 문자열 길이 출력
- 모든 문자가 다른 경우 (예: “abcd”) → 1 출력
- 길이가 소수인 경우 (예: “abcab”, 길이 5) → 1 출력 (주기 없음)
- 부분적 반복 (예: “ababab”) → 주기 찾기 정확히 수행
- 매우 큰 문자열 (최대 1,000,000) → O(n) 시간에 처리
- 10개 이하의 다중 테스트 케이스 → 마침표로 종료
제출 전 점검
- 문자열 입력이 “.“인 경우 종료하는지 확인
- Failure function 초기화가 0으로 되어 있는지 확인
- 주기 계산 후 len % period == 0 조건 확인
- 출력 형식 (개행 문자 “\n” 사용) 확인
- Fast I/O 설정 (ios::sync_with_stdio, cin.tie) 확인
- 배열 인덱스가 0부터 len-1까지 올바르게 처리되는지 확인
참고자료/유사문제
- KMP 알고리즘: Knuth-Morris-Pratt pattern matching (O(n+m) 시간)
- 관련 개념: String periodicity, Failure function (Z-algorithm도 유사하게 적용 가능)
- 유사 문제: BOJ 1786 (찾기), BOJ 2180 (문자열 주기)
- 더 읽을거리: “Introduction to Algorithms” - Chapter 32 (String Matching)
![Featured image of post [Algorithm] C++ 백준 4354번: 문자열 제곱](/post/algorithm/2025-12-02-boj-4354-string-power-period-kmp-cpp-solution/wordcloud_hu_d2530027e8748ff1.png)
![[Algorithm] C++ 백준 1725번: 히스토그램](/post/algorithm/2025-12-02-boj-1725-histogram-maxarea-stack-cpp-solution/wordcloud_hu_a9b77b8cde0366cb.png)
![[Algorithm] C++ 백준 2626번: 헬기착륙장](/post/algorithm/2025-12-02-boj-2626-helicopter-landing-site-minenc-cpp-solution/wordcloud_hu_4445322990b006e3.png)
![[Algorithm] C++ 백준 4354번: 문자열 제곱](/post/algorithm/2025-12-02-boj-4354-string-power-period-kmp-cpp-solution/wordcloud_hu_cd8c6924b1ac5ab.png)
![[Algorithm] C++ 백준 7577번: 탐사](/post/algorithm/2025-12-02-boj-7577-exploration-difference-constraints-spfa-cpp-solution/wordcloud_hu_2a0dd3ac39086d6a.png)
![[Algorithm] C++ 백준 8096번 모노크로매틱 삼각형](/post/algorithm/2025-12-02-boj-8096-monochromatic-triangles-graph-cpp-solution/wordcloud_hu_1363dd3799982cba.png)
![[Algorithm] C++ 백준 9250번: 문자열 집합 판별](/post/algorithm/2025-08-14-boj-9250-string-set-membership-aho-corasick-cpp-solution/wordcloud_hu_18eda8d77d438bc5.png)
![[Algorithm] C++ 백준 13576번: Prefix와 Suffix](/post/algorithm/2025-08-14-boj-13576-prefix-and-suffix-cpp-solution/wordcloud_hu_72d54380bd8dc598.png)
![[Algorithm] C++ 백준 14959번: Slot Machines - KMP로 최소 주기 O(n)](/post/algorithm/2025-08-14-boj-14959-slot-machines-cpp-solution/wordcloud_hu_e15b303f3a09b926.png)
![[Algorithm] C++ 백준 16496번: 큰 수 만들기](/post/algorithm/2025-12-02-boj-16496-largest-number-greedy-sorting-cpp-solution/wordcloud_hu_9f9372bd1ae0bc2e.png)