Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
A string is bad only in one exact situation: it contains 2025 and does not contain 2026. If either side of that sentence breaks, you're done.
So the answer is the cheaper of two plans: force some length- window to become 2026, or edit the string so there is no 2025 anywhere.
Forcing 2026 is easy: for every window , count how many characters differ from 2026; take the minimum.
To remove all 2025, scan left to right with a tiny automaton tracking how much of 2025 is currently matched as a suffix. Never allow the matched length to become .
Let be the minimum cost after processing characters, where is the length of the longest suffix equal to a prefix of 2025. Try replacing the next character with 0, 2, 5, or 6; skip transitions that complete 2025. Then answer is .
The definition looks a little weird, so simplify it first.
A string is a New Year string if:
2026, or2025.That means the only strings that fail are strings that contain 2025 while also not containing 2026. So we can make the string valid in either of two ways:
2026,2025.The minimum answer is the cheaper of those two. No need to overcook this. It is an 800, not a villain origin story.
Making 2026
If we want the final string to contain 2026, we only need to choose one window of length and change that window into 2026.
For a window starting at index , the cost is:
Take the minimum over all windows.
Everything outside that window can stay unchanged, because the condition only asks for at least one occurrence of 2026.
Removing all 2025
Now we need the minimum number of edits so the final string avoids 2025 as a substring.
Since , many things would work, but the cleanest robust method is a pattern-avoidance DP.
Let the forbidden pattern be:
Define:
as the minimum number of changes after building the first characters, where is the length of the longest suffix of the built string that is also a prefix of 2025.
So can be . We never allow , because that means we just formed the forbidden substring 2025.
For each position , we try every possible replacement character . The cost of choosing is if , otherwise .
Then we update the matched prefix length. For example, if our current suffix state is represented by the first characters of 2025, we append , and compute the longest suffix of that new string that is also a prefix of 2025.
If that new length is , skip it. That transition creates 2025, which is exactly the crap we are trying to avoid.
At the end, the cost to remove all 2025 is:
Why this is correct
For the 2026 plan, any valid final string containing 2026 has some occurrence of 2026. Looking at that occurrence gives one window whose mismatch count is at most the total number of edits. Conversely, changing that cheapest window is enough. So the window minimum is exact.
For the no-2025 plan, the DP stores exactly the information needed to know whether the next character completes 2025: the longest suffix that could still become the forbidden pattern. This is the standard finite automaton idea, just tiny enough to write directly. Every edited string avoiding 2025 corresponds to one valid DP path, and every valid DP path builds a string avoiding 2025. Therefore the DP minimum is exact.
Finally, a string is valid if it satisfies either plan, so the answer is:
Complexity
There are positions, states, and possible characters per transition. The transition itself checks strings of length at most , so this is basically constant-time per test case.
Formally:
which is hilariously fine for and .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int nextState(int state, char c) {
string p = "2025";
string cur = p.substr(0, state) + c;
for (int len = 4; len >= 0; --len) {
if (len > (int)cur.size()) continue;
bool ok = true;
for (int i = 0; i < len; ++i) {
if (cur[(int)cur.size() - len + i] != p[i]) {
ok = false;
break;
}
}
if (ok) return len;
}
return 0;
}
int main() {
setIO();
int t;
cin >> t;
const string make = "2026";
const string alphabet = "0256";
while (t--) {
int n;
string s;
cin >> n >> s;
int make2026 = 4;
for (int i = 0; i + 4 <= n; ++i) {
int cost = 0;
for (int j = 0; j < 4; ++j) {
cost += (s[i + j] != make[j]);
}
make2026 = min(make2026, cost);
}
const int INF = 1e9;
vector<vector<int>> dp(n + 1, vector<int>(4, INF));
dp[0][0] = 0;
for (int i = 0; i < n; ++i) {
for (int state = 0; state < 4; ++state) {
if (dp[i][state] == INF) continue;
for (char c : alphabet) {
int ns = nextState(state, c);
if (ns == 4) continue;
dp[i + 1][ns] = min(dp[i + 1][ns], dp[i][state] + (s[i] != c));
}
}
}
int avoid2025 = *min_element(dp[n].begin(), dp[n].end());
cout << min(make2026, avoid2025) << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int nextState(int state, char c) {
string p = "2025";
string cur = p.substr(0, state) + c;
for (int len = 4; len >= 0; --len) {
if (len > (int)cur.size()) continue;
bool ok = true;
for (int i = 0; i < len; ++i) {
if (cur[(int)cur.size() - len + i] != p[i]) {
ok = false;
break;
}
}
if (ok) return len;
}
return 0;
}
int main() {
setIO();
int t;
cin >> t;
const string make = "2026";
const string alphabet = "0256";
while (t--) {
int n;
string s;
cin >> n >> s;
int make2026 = 4;
for (int i = 0; i + 4 <= n; ++i) {
int cost = 0;
for (int j = 0; j < 4; ++j) {
cost += (s[i + j] != make[j]);
}
make2026 = min(make2026, cost);
}
const int INF = 1e9;
vector<vector<int>> dp(n + 1, vector<int>(4, INF));
dp[0][0] = 0;
for (int i = 0; i < n; ++i) {
for (int state = 0; state < 4; ++state) {
if (dp[i][state] == INF) continue;
for (char c : alphabet) {
int ns = nextState(state, c);
if (ns == 4) continue;
dp[i + 1][ns] = min(dp[i + 1][ns], dp[i][state] + (s[i] != c));
}
}
}
int avoid2025 = *min_element(dp[n].begin(), dp[n].end());
cout << min(make2026, avoid2025) << '\n';
}
return 0;
}