公式

D - ビーズ列 / Bead Sequence 解説 by admin

gpt-5.5-high

Overview

We consider strings of length \(N\) consisting of A / B as states, and find the minimum number of operations to transform \(S\) into \(T\) using 3 types of operations.

Since the cost of each operation is \(1\), we can find the shortest number of steps by performing Breadth-First Search (BFS) on a graph where states are vertices and operations are edges.

Discussion

In this problem, we can perform the following operations on the current bead sequence:

  • Left rotation
  • Right rotation
  • Replace the entire string by repeating the first \(d\) characters

For example, when \(N = 6\) and the current string is ABBAAB:

  • Left rotation gives BBAABA
  • Right rotation gives BABBAA
  • Choosing \(d = 2\) repeats the first \(2\) characters AB three times to get ABABAB

The key point here is that the number of states is finite.

Since there are \(2\) types of characters (A and B) and the length is \(N\), the maximum number of possible strings is

\(2^N\)

The number of possible operation sequences is infinite. For example, by alternating left and right rotations, you can return to the same state any number of times.

Therefore, a naive approach that tries all possible operation sequences will never terminate.

However, if we avoid revisiting states that have already been explored, the number of states to examine is at most \(2^N\).

Also, since all operations have the same cost of \(1\), BFS is suitable for finding the shortest number of steps.

BFS explores states in order of distance \(0\), distance \(1\), distance \(2\), …, so the distance when \(T\) is first reached is the minimum number of operations.

Algorithm

  1. Enumerate all positive divisors \(d\) of \(N\) where \(d < N\).
  2. Start BFS with \(S\) as the starting point.
  3. For each state \(x\), generate the following transitions:
    • Left rotation: x[1:] + x[0]
    • Right rotation: x[-1] + x[:-1]
    • For each divisor \(d\), repeat the first \(d\) characters:
      • x[:d] * (N // d)
  4. If the state has not been visited yet, set its distance to the current distance \(+1\) and add it to the queue.
  5. If \(T\) is found during BFS, output that distance.
  6. If \(T\) is not reachable after the search completes, output -1.

The BFS flow is as follows:

dist[S] = 0
queue = [S]

while queue is not empty:
    x = dequeue from queue

    if x == T, output dist[x] as the answer

    generate all states reachable from x by one operation
    if unvisited, record the distance and add to queue

Complexity

Let \(R\) be the number of states reachable from \(S\), and \(D\) be the number of positive divisors of \(N\) that are less than \(N\).

The transitions from each state consist of \(2\) (left rotation and right rotation) plus \(D\) (pattern duplications).

Also, generating a string takes time proportional to the length \(N\).

  • Time complexity: \(O(R(D+2)N)\)
    Since \(R \leq 2^N\), the upper bound is \(O(2^N(D+2)N)\)
  • Space complexity: \(O(RN)\)

Implementation Notes

Use dist as a dictionary to record the shortest distance for each string.

dist = {S: 0}

Use deque as the queue for BFS.

from collections import deque
q = deque([S])

Since the divisors used for pattern duplication don’t need to be computed each time, enumerate them at the beginning.

divs = [(d, N // d) for d in range(1, N) if N % d == 0]

With this, for each state we can generate transitions for the pre-enumerated divisors simply by:

y = x[:d] * m

Also, there are cases where rotation operations produce the same string, or different operations reach the same state, but we can prevent redundant exploration by checking whether the state already exists in dist.

Source Code

import sys
from collections import deque

def main():
    input = sys.stdin.readline
    N = int(input())
    S = input().strip()
    T = input().strip()

    divs = [(d, N // d) for d in range(1, N) if N % d == 0]

    dist = {S: 0}
    q = deque([S])

    while q:
        x = q.popleft()
        cur = dist[x]

        if x == T:
            print(cur)
            return

        nd = cur + 1

        y = x[1:] + x[0]
        if y not in dist:
            dist[y] = nd
            q.append(y)

        y = x[-1] + x[:-1]
        if y not in dist:
            dist[y] = nd
            q.append(y)

        for d, m in divs:
            y = x[:d] * m
            if y not in dist:
                dist[y] = nd
                q.append(y)

    print(-1)

if __name__ == "__main__":
    main()

This editorial was generated by gpt-5.5-high.

投稿日時:
最終更新: