Official

B - dp Editorial by evima


A naive solution is to try all \((L, R)\) such that \(1 \leq L \leq R \leq N\), find all resulting \(S\), and print the lexicographically smallest of these strings plus the original \(S\).
It will print the correct answer, but there are \(\mathrm{O}(N^2)\) pairs \((L, R)\), and each string is of length \(N\), so it takes \(\mathrm{O}(N^3)\) time, which is too much. Let us try to narrow down the pairs to check.

First, if \(S\) solely consists of d, it is optimal to skip the operation and print \(S\) as it is. Below, consider the case \(S\) contains p.
Let \(i\) be the leftmost index of p in \(S\). Also, let \(g(l, r)\) be the \(S\) resulting from the choice \((L, R) = (l, r)\).

Here, the following holds:

For any \(g(L, R), L \neq i\), there is an \(R'\) such that \(g(i, R') \lt g(L, R)\). \((\ast)\)

We will prove this by division into cases according to the magnitude relationship between \(i\) and \(L\).

1. If \(i \lt L\):

Let us compare \(g(i,i)\) and \(g(L,R)\). The first \((L-1)\) characters are the same, but the \(L\)-th characters of \(g(i,i)\) and \(g(L,R)\) are d and p, respectively, so \(g(i, i) \lt g(L, R)\).

2. If \(i \gt L\):

Let us compare \(g(i, R)\) and \(g(L, R)\). The \(1\)-st through \((L-1)\)-th characters and the \((R+1)\)-th through \(N\)-th characters are the same, so we look at the rest. The \(L\)-th through \((i-1)\)-th characters of \(S\) are all d from the assumption, so let \(U\) be a string of length \(i-L\) solely consisting of d, and the \(i\)-th through \(R\)-th characters of the two strings are as follows.

  • the \(i\)-th through \(R\)-th characters of \(g(i,R)\): \(U + f(T)\)
  • the \(i\)-th through \(R\)-th characters of \(g(L,R)\): \(f(U + T) = f(T) + f(U)\)

Now, for each of \(U + f(T)\) and \(f(T) + f(U)\), consider the leftmost index of p. (They have the same length, so if the leftmost positions of p in these strings are different, we can know which string is smaller.)
We use division into cases according to whether \(f(T)\) contains p.

a. If \(f(T)\) contains no p:

\(U+f(T)\) solely consists of d and contains no p. On the other hand, \(f(U)\) solely consists of p, so the \((\vert T \vert + 1)\)-th character of \(f(T) + f(U)\) is p. Therefore, \(U + f(T) \lt f(T) + f(U)\).

b. If the leftmost index of p in \(f(T)\) is \(j\):

The leftmost index of p in \(U+f(T)\) is \(\vert U \vert + j\), while that of \(f(T)+f(U)\) is \(j\). Therefore, \(U + f(T) \lt f(T) + f(U)\).

Thus, we have \(U + f(T) \lt f(T) + f(U)\) in both cases. Therefore, \(g(i, R) \lt g(L, R)\) holds in case 2.

From the above, \((\ast)\) holds in all cases. By using \((\ast)\), we can see that only the pairs \((L, R)\) such that \(L = i\) need to be checked to find the answer, because for any \(g(L,R)\) \((L\neq i)\), there is a smaller string \(g(i,R')\).
Now, the number of strings to be checked decreases from \(\mathrm{O}(N^2)\) to \(\mathrm{O}(N)\), for a total complexity of \(\mathrm{O}(N^2)\), which is fast enough.

  • Sample implementation (PyPy)
def f(T):
  U = [c for c in reversed(T)]
  for i in range(len(U)):
    U[i] = 'd' if U[i] == 'p' else 'p'
  return "".join(U)

N = int(input())
S = input()
L = 0
while L != N and S[L] == 'd':
  L += 1
ans = S
for R in range(L + 1, N + 1):
  ans = min(ans, S[:L] + f(S[L:R]) + S[R:])
print(ans)

posted:
last update: