F - 11/22 Substring Editorial by en_translator
The key to this problem is how to cover all the \(11/22\) strings.
This can be done by noticing the center /
of a \(11/22\) string. That is, fix the central /
and inspect 1 and 2 extending left and right. The algorithm is as follows:
- Let
ans
be the variable to manage the answer. Initially,ans
\(= 0\). - For each \(i = 1, 2, \dots, N\) in order, do the following.
- If \(S[i] \neq\)
/
, do nothing. - If \(S[i] =\)
/
, repeat the following procedure, using a variable \(d\) (initialized with \(d = 0\)) that manages the length of 1 and 2 extending to left and right.- Let \(l = i - (d + 1)\) and \(r = i + (d + 1)\).
- If \(1 \leq l \leq N\) is violated, terminate the loop.
- If \(1 \leq r \leq N\) is violated, terminate the loop.
- If \(S[l] =\)
1
is violated, terminate the loop. - If \(S[r] =\)
2
is violated, terminate the loop. - Otherwise, there are
1
and2
in the left and right, respectively, so the extended span satisfies the conditions for a \(11/22\) string. Set \(d\) to \(d+1\).
- The length of the \(11/22\) string obtained is \(1 + 2d\), so set
ans
to \(\max(\mathrm{ans}, 1 + 2d)\).
- If \(S[i] \neq\)
- The final value
ans
is the answer.
Let us consider the complexity. Some may think that this costs \(\mathrm{O}(N^2)\), because each loop costs at worst \(\mathrm{O}(N)\) time, but actually it is \(\mathrm{O}(N)\).
This can be proved as follows. Throughout the algorithm, if the “procedure” is repeated \(\mathrm{O}(N)\) times in total, then the complexity can be considered \(\mathrm{O}(N)\), so we prove this. For each \(j\) with \(1 \leq j \leq N\), consider how many times \(j\) is picked as \(l\). Then, this is limited to the case where \(i\) is the first occurrence of /
when scanning from \(j\) to the right, so \(j\) is picked as \(l\) at most once. Therefore, each \(j\) is picked at most once as \(l\) throughout the algorithm, so the “procedure” is executed at most \(\mathrm{O}(N)\) times. Thus, it has been proved.
Hence, the problem runs in \(\mathrm{O}(N)\) time, which is fast enough.
- Sample code (C++)
#include <iostream>
#include <string>
using namespace std;
int main() {
int N;
string S;
cin >> N >> S;
int ans = 0;
for (int i = 0; i < N; i++) {
if (S[i] != '/') continue;
int d = 0;
while (true) {
int j = i - (d + 1);
int k = i + (d + 1);
if (!(0 <= j and j < N)) break;
if (!(0 <= k and k < N)) break;
if (S[j] != '1') break;
if (S[k] != '2') break;
d++;
}
ans = max(ans, 1 + d * 2);
}
cout << ans << "\n";
}
posted:
last update: