문제
알파벳 소문자로 이루어진 두 문자열 a와 b가 주어졌을 때, ab는 두 문자열을 이어붙이는 것을 뜻한다. 예를 들어, a="abc", b="def"일 때, ab="abcdef"이다.
이러한 이어 붙이는 것을 곱셈으로 생각한다면, 음이 아닌 정수의 제곱도 정의할 수 있다.
- a^0 = "" (빈 문자열)
- a^(n+1) = a*(a^n)
문자열 s가 주어졌을 때, 어떤 문자열 a에 대해서 s=a^n을 만족하는 가장 큰 n을 찾는 프로그램을 작성하시오.
입력
입력은 10개 이하의 테스트 케이스로 이루어져 있다. 각각의 테스트 케이스는 s를 포함한 한 줄로 이루어져 있다. s의 길이는 적어도 1이며, 백만글자를 넘지 않는다. 마지막 테스트 케이스의 다음 줄은 마침표이다.
출력
각각의 테스트 케이스에 대해, s=a^n을 만족하는 가장 큰 n을 찾은 뒤 출력한다.
예제 입력 1
abcd
aaaa
ababab
.
예제 출력 1
1
4
3
나의 풀이
이 문제는 KMP 알고리즘에서 다룬 접두사, 접미사의 최대 개수를 구하는 함수를 이용한다. 알고보니 이 함수의 이름이
failure function
이라고 한다. 이 함수를 통해 결과값으로 나온 배열을table
이라고 하고, 입력받은 문자열을string
이라고 한다면 이 문제를 푸는 공식(?)은 다음과 같다.len(string) // (len(string) - table[-1])
즉, 문자열의 길이 // (문자열의 길이 - failure function의 마지막 값)이다.
예를들어,
ababab
가 있다면failure function
을 거쳐 나온 배열은 다음과 같다,a b a b a b 0 0 1 2 3 4
여기서 공식에 대입해보면
6 // (6 - 4) = 3
이다.ab
가 3번 반복되므로 정답과 같다. 이것의 원리는 문자열의 길이에서 4를 빼면 2인데 2는 곧ab
의 길이이므로 즉, 반복되는 가장 짧은 부분 문자열의 길이와 같다는 것이다.그러나 여기서는 예외가 존재한다. 만약,
abababa
라면 결과값이 어떻게 될까?a b a b a b a 0 0 1 2 3 4 5
abababa
의 failure function의 결과값은 위와 같다. 공식을 적용해보자.7 // (7 - 5) = 3
이다. 그러나 이 문자열의 경우 마지막a
가 가장 짧은 부분 문자열인ab
와 다르기때문에 정답은 1이 나와야한다. 이러한 경우를 잘 살펴보면 문자열의 길이가 홀수인 경우에 해당한다. 따라서 해당 예외를 잡아내기 위해서는len(string) % (len(string) - table[-1]) != 0
을 확인해주면 된다. 즉, 나눈 나머지가 0인가를 판단하여 0이 아니라면 1을 반환해준다면 이 문제는 해결할 수 있다.
코드
# 4354번 문자열 제곱
def failure(p):
tmp = [0] * len(p)
j = 0
for i in range(1, len(p)):
while j > 0 and p[i] != p[j]:
j = tmp[j-1]
if p[i] == p[j]:
j += 1
tmp[i] = j
return tmp
while True:
string = input()
if string == '.':
break
table = failure(string)
if len(string) % (len(string) - table[-1]) != 0: # 나머지 확인
print(1)
else:
print(len(string) // (len(string) - table[-1]))
'Programming > Algorithm' 카테고리의 다른 글
[백준10266번] 시계 사진들 / Python3 (0) | 2020.12.23 |
---|---|
[백준1305번] 광고 / Python3 (0) | 2020.12.22 |
[백준1786번] 찾기 / Python3 (0) | 2020.12.22 |
[Algorithm] KMP 알고리즘 with Python (0) | 2020.12.22 |
[백준17404번] RGB거리 2 / Python3 (0) | 2020.12.21 |