[프로그래머스]-문자열 압축

이정연·2022년 10월 14일
0

CodingTest

목록 보기
42/165

💬 문자열 압축

[Class2][문자열 압축](https://school.programmers.co.kr/learn/courses/30/lessons/60057)

문제 설명


데이터 처리 전문가가 되고 싶은 "어피치"는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다.
간단한 예로 "aabbaccc"의 경우 "2a2ba3c"(문자가 반복되지 않아 한번만 나타난 경우 1은 생략함)와 같이 표현할 수 있는데, 이러한 방식은 반복되는 문자가 적은 경우 압축률이 낮다는 단점이 있습니다. 예를 들면, "abcabcdede"와 같은 문자열은 전혀 압축되지 않습니다. "어피치"는 이러한 단점을 해결하기 위해 문자열을 1개 이상의 단위로 잘라서 압축하여 더 짧은 문자열로 표현할 수 있는지 방법을 찾아보려고 합니다.

예를 들어, "ababcdcdababcdcd"의 경우 문자를 1개 단위로 자르면 전혀 압축되지 않지만, 2개 단위로 잘라서 압축한다면 "2ab2cd2ab2cd"로 표현할 수 있습니다. 다른 방법으로 8개 단위로 잘라서 압축한다면 "2ababcdcd"로 표현할 수 있으며, 이때가 가장 짧게 압축하여 표현할 수 있는 방법입니다.

다른 예로, "abcabcdede"와 같은 경우, 문자를 2개 단위로 잘라서 압축하면 "abcabc2de"가 되지만, 3개 단위로 자른다면 "2abcdede"가 되어 3개 단위가 가장 짧은 압축 방법이 됩니다. 이때 3개 단위로 자르고 마지막에 남는 문자열은 그대로 붙여주면 됩니다.

압축할 문자열 s가 매개변수로 주어질 때, 위에 설명한 방법으로 1개 이상 단위로 문자열을 잘라 압축하여 표현한 문자열 중 가장 짧은 것의 길이를 return 하도록 solution 함수를 완성해주세요.

제한사항


  • s의 길이는 1 이상 1,000 이하입니다.
  • s는 알파벳 소문자로만 이루어져 있습니다.

입출력 예


sresult
"aabbaccc"7
"ababcdcdababcdcd"9
"abcabcdede"8
"abcabcabcabcdededededede"14
"xababcdcdababcdcd"17

입출력 예에 대한 설명

입출력 예 #1

문자열을 1개 단위로 잘라 압축했을 때 가장 짧습니다.

입출력 예 #2

문자열을 8개 단위로 잘라 압축했을 때 가장 짧습니다.

입출력 예 #3

문자열을 3개 단위로 잘라 압축했을 때 가장 짧습니다.

입출력 예 #4

문자열을 2개 단위로 자르면 "abcabcabcabc6de" 가 됩니다.
문자열을 3개 단위로 자르면 "4abcdededededede" 가 됩니다.
문자열을 4개 단위로 자르면 "abcabcabcabc3dede" 가 됩니다.
문자열을 6개 단위로 자를 경우 "2abcabc2dedede"가 되며, 이때의 길이가 14로 가장 짧습니다.

입출력 예 #5

문자열은 제일 앞부터 정해진 길이만큼 잘라야 합니다.
따라서 주어진 문자열을 x / ababcdcd / ababcdcd 로 자르는 것은 불가능 합니다.
이 경우 어떻게 문자열을 잘라도 압축되지 않으므로 가장 짧은 길이는 17이 됩니다.

# 📖 가져다 쓰기

처음에는 스택을 떠올렸다. 왜냐하면 문자열에서 특정 문자열을 검색하는 문제이기 때문이다. 

그러나 시간복잡도를 구해보고 브루트 포스로 풀어야겠다고 생각했다. 

+ 입력 데이터 개수: 1000 👉🏻 O(N^2*logN)까지 가능
+ 브루트 포스로 예상되는 시간 복잡도 👉🏻 O(N^2)

# 📐 과정 설계/관리

![연습장-63](https://user-images.githubusercontent.com/88064555/181485252-1849708b-fcbe-4cd6-86f2-df371ecad727.jpg)


입력: aabbaccc가 들어왔을 때를 예시로 진행해보겠다.

먼저 1부터 절반까지 문자열을 나누는 모든 경우를 구한다. 이 때, 절반까지 탐색하는 이유는 어차피 절반을 넘어가는 순간 문자열 압축이 되지 않기 때문이다.

(그런데 최종적인 코드는 불필요하더라도 1부터 전체를 나누어 풀었다. 그 이유는 문자열 길이가 1일때는 절반으로 쪼개지지 않기 때문에 에러가 발생한다.)

그렇게 하여 각각의 압축된 문자열 길이를 비교하여 최소값을 반환해주면 정답이다.


![연습장-64](https://user-images.githubusercontent.com/88064555/181485322-650d8dfd-34c9-4417-a68c-71ee0562023a.jpg)

![연습장-65](https://user-images.githubusercontent.com/88064555/181485372-19362a11-703d-498d-940d-781786b7da2a.jpg)


이제부터는 나누어진 각 문자열에 대하여 어떻게 압축이 진행되는지를 설명해보도록 하겠다.

가장 첫 번째 인덱스부터 시작하여 다음 인덱스를 비교해보아 같은 값이 나오면 count를 증가시키며 계속 탐색한다.

만약 count가 1이라면 그대로 압축 문자열에 붙여주고 2 이상이라면 count와 함께 같이 붙여준다.

그렇게 문자열 끝까지 탐색을 마치면 최종적인 압축 문자열이 생성되고 이를 정답 후보군 리스트에 넣어준다.

마지막에 정답 후보군 리스트에서 최소값을 선택해주면 그것이 곧 정답 !!!

# 👨🏻‍💻 CODE

```python
def solution(s):
    candidates = []

    # 문자열 분리
    for a in range(1,len(s)+1):
        i=0
        arr = []
        while i+a<len(s):
            arr.append(s[i:i+a])
            i += a
        arr.append(s[i:])

        answer = ""
        i=0
        while 0<=i<len(arr):
            count = 1
            if i != len(arr)-1:
                while arr[i] == arr[i+1]:
                    count += 1
                    i += 1

                    if i == len(arr)-1:
                        break
            
            if count == 1:
                answer += arr[i]
            else:
                answer += str(count) + arr[i]
            
            i += 1

        candidates.append(len(answer))

    return min(candidates)
profile
0x68656C6C6F21

0개의 댓글