문제 설명
'A'와 'B'로만 구성된 문자열이 주어집니다. 임의의 문자를 토글(다른 문자로 변경)하면 주어진 문자열을 다른 문자열로 변환할 수 있으며, 이렇게 만들 수 있는 변환의 수는 매우 많습니다. 이때 우리가 구해야 할 것은 가능한 변환 중 최대 가중치 변환의 가중치입니다.
문자열의 가중치는 다음 공식으로 계산됩니다.
문자열의 가중치 = 전체 쌍(pair)의 가중치 합 + 단일 문자의 가중치 합 − 총 토글 횟수
가중치 계산 규칙
연속된 두 문자는 서로 다를 때만 하나의 쌍으로 간주됩니다.
한 쌍의 가중치(두 문자가 서로 다른 경우) = 4
단일 문자의 가중치 = 1
입출력 예시
입력 문자열이 "AA"라면 결과는 3입니다.
"AA"에서 파생될 수 있는 모든 변환은 "AA", "AB", "BA", "BB"입니다.
최대 가중치 변환은 "AB" 또는 "BA"이며, 가중치는 "한 쌍 − 한 번의 토글" = 4 − 1 = 3입니다.
알고리즘
이 문제는 재귀 호출에 메모이제이션을 결합한 동적 계획법으로 효율적으로 해결할 수 있습니다. 각 위치에서 현재 문자를 단일 문자로 처리할지, 바로 뒤의 문자와 쌍으로 묶을지를 판단하고 두 선택지 중 더 큰 가중치를 취합니다.
1. n == 1인 경우 maxWeight(str[0..n-1]) = 1 2. str[0] != str[1]인 경우 (서로 다른 문자로 쌍 형성) maxWeight(str[0..n-1]) = Max(1 + maxWeight(str[1..n-1]), 4 + getMaxRec(str[2..n-1])) 3. 그 외의 경우 (같은 문자로 쌍을 만들려면 토글 1회 필요) maxWeight(str[0..n-1]) = Max(1 + maxWeight(str[1..n-1]), 3 + getMaxRec(str[2..n-1]))
여기서 str[i]와 str[i+1]이 같은 문자라면 쌍을 만들기 위해 반드시 한 번의 토글이 필요하므로, 쌍 가중치 4에서 토글 비용 1을 제외한 3이 더해집니다.
C++ 구현 예제
#include<bits/stdc++.h>
using namespace std;
int getMaxRec(string &str, int i, int n, int lookup[]){
if (i >= n) {
return 0;
}
if (lookup[i] != -1) {
return lookup[i];
}
int ans = 1 + getMaxRec(str, i + 1, n, lookup);
if (i + 1 < n) {
if (str[i] != str[i+1]) {
ans = max(4 + getMaxRec(str, i + 2, n, lookup), ans);
} else {
ans = max(3 + getMaxRec(str, i + 2, n, lookup), ans);
}
}
return lookup[i] = ans;
}
int getMaxWeight(string str){
int n = str.length();
int lookup[n];
memset(lookup, -1, sizeof lookup);
return getMaxRec(str, 0, str.length(), lookup);
}
int main(){
string str = "AA";
cout << "Result = " << getMaxWeight(str) << endl;
return 0;
}
코드 설명
getMaxRec 함수는 인덱스 i부터 문자열 끝까지의 최대 가중치를 재귀적으로 계산합니다. lookup 배열에 이미 계산된 결과를 저장하여 중복 연산을 제거하기 때문에 전체 시간 복잡도는 O(n)입니다. 인접한 두 문자가 서로 다르면 쌍 가중치 4를, 같으면 토글 비용을 반영한 3을 더하는 것이 핵심 로직입니다.
실행 결과
위 프로그램을 컴파일 후 실행하면 다음과 같은 출력을 얻습니다.
Result = 3