公式

F - 11/22 Substring 解説 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 and 2 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)\).
  • 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";
}

投稿日時:
最終更新: