Цветная полоска
Условие
Строка длины из первых букв английского алфавита.
Выведите минимальное количество замен над строкой , чтобы все , и саму строку .
Решение
Решение
Решение авторское жадное.
Опять не комбинаторное ДП.
Обозначим строку, которую мы ищем, за .
- Двуменное — минимальное количество замен, чтобы на префиксе был валидный и
- Начальное значение , так как мы не заменяли, и для всех остальных случаев.
- Пусть мы выбрали, что , значит по условию . Значит из всех состояний минимальный.
- Ответ минимальное значение из .
Это медленно .
Соптимизируем до поддерживая префиксные минимумы для состояния . И тогда выбор оптимального состояния, через которое мы обновим будет за
void solve() {
int n, k;
cin >> n >> k;
vector<vector<int>> ans(k, vector<int>(n));
vector<vector<int>> p(k, vector<int>(n));
vector<int> pref(k);
vector<int> suf(k);
for (int _ = 0; _ < n; _++) {
char c;
cin >> c;
if (_ == 0) {
ans[c - 'A'][0] = 0;
p[c - 'A'][0] = -1;
for (int i = 0; i < k; i++) {
if (i != c - 'A') {
ans[i][0] = 1;
p[i][0] = -1;
}
}
} else {
for (int x = 0; x < k; x++) {
if (x == 0) {
ans[x][_] = ans[suf[x + 1]][_ - 1];
p[x][_] = suf[x + 1];
} else if (x == k - 1) {
ans[x][_] = ans[pref[x - 1]][_ - 1];
p[x][_] = pref[x - 1];
} else {
int a = pref[x - 1];
int b = suf[x + 1];
if (ans[a][_ - 1] > ans[b][_ - 1]) swap(a, b);
ans[x][_] = ans[a][_ - 1];
p[x][_] = a;
}
if (x != c - 'A') {
ans[x][_]++;
}
}
}
pref[0] = 0;
for (int i = 1; i < k; i++) {
if (ans[i][_] < ans[pref[i - 1]][_]) {
pref[i] = i;
} else {
pref[i] = pref[i - 1];
}
}
suf[k - 1] = k - 1;
for (int i = k - 2; i >= 0; i--) {
if (ans[i][_] < ans[suf[i + 1]][_]) {
suf[i] = i;
} else {
suf[i] = suf[i + 1];
}
}
}
pair<int, int> b = {INT_MAX, -1};
for (int i = 0; i < k; i++) {
b = min(b, {ans[i][n - 1], i});
}
cout << b.first << '\n';
string res;
char c = b.second;
for (int i = n - 1; i >= 0; i--) {
res += (char)(c + 'A');
c = p[c][i];
}
reverse(res.begin(), res.end());
cout << res;
}