ABBC or BACB
Explicación
La observación un poco rara que hay que hacer aquí es que el proceso de reemplazo se puede pensar como que las B “se comen” las A y dejan C donde estaban.
Este proceso se ve más claro en el 5.º caso de ejemplo:
AAAAAAB
AAAAABC
AAAABCC
...
BCCCCCCComo las B dejan C atrás cuando se comen una A, tienen que elegir una dirección y comprometerse con ella.
Con eso, solo necesitamos esta información:
- Cuántas “rachas” de A hay y sus tamaños
- Cuántas B hay adyacentes a una racha de A.
Nótese que, como el string inicial solo puede alternar entre A y B, puede haber como máximo una racha de A más que B disponibles.
Si este es el caso, tenemos que renunciar a la racha más pequeña de A que ocurra. Si no, podemos imprimir la suma de todas las rachas de A —es decir, el número total de A en el string.
Implementación
Complejidad temporal:
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
int main() {
int test_num;
std::cin >> test_num;
for (int t = 0; t < test_num; t++) {
std::string str;
std::cin >> str;
str += 'X'; // Añadimos una X por conveniencia en el bucle de abajo
int b_amts = 0;
vector<int> a_runs;
int a_total = 0;
char last = str[0];
int run_len = 1;
for (int i = 1; i < str.size(); i++) {
if (str[i] != last) {
if (last == 'A') {
a_runs.push_back(run_len);
a_total += run_len;
} else if (last == 'B') {
// Cualquier racha de B puede tener como máximo 2 adyacentes a A
b_amts += std::min(run_len, 2);
}
run_len = 0;
}
last = str[i];
run_len++;
}
// Aplicamos la fórmula descrita en la explicación de arriba
if (b_amts < a_runs.size()) {
int exclude = *std::min_element(a_runs.begin(), a_runs.end());
cout << a_total - exclude << '\n';
} else {
cout << a_total << '\n';
}
}
}import java.io.*;
import java.util.*;
public class ABBCorBACB {
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
int testNum = Integer.parseInt(read.readLine());
for (int t = 0; t < testNum; t++) {
// Añadimos una X por conveniencia en el bucle de abajo
String str = read.readLine() + 'X';
int bAmts = 0;
List<Integer> aRuns = new ArrayList<>();
int aTotal = 0;
char last = str.charAt(0);
int runLen = 1;
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) != last) {
if (last == 'A') {
aRuns.add(runLen);
aTotal += runLen;
} else if (last == 'B') {
// Cualquier racha de B puede tener como máximo 2 adyacentes a A
bAmts += Math.min(runLen, 2);
}
runLen = 0;
}
last = str.charAt(i);
runLen++;
}
// Aplicamos la fórmula descrita en la explicación de arriba
if (bAmts < aRuns.size()) {
System.out.println(aTotal - Collections.min(aRuns));
} else {
System.out.println(aTotal);
}
}
}
}from itertools import groupby
for _ in range(int(input())):
string = input()
b_amts = 0
a_runs = []
for char, amt in groupby(string):
if char == "A":
a_runs.append(len(list(amt)))
else:
# Cualquier racha de B puede tener como máximo 2 adyacentes a A
b_amts += min(len(list(amt)), 2)
# Aplicamos la fórmula descrita en la explicación de arriba
if b_amts < len(a_runs):
print(sum(a_runs) - min(a_runs))
else:
print(sum(a_runs))