Official

E - 円環文字列の辞書順ランキング / Lexicographic Ranking of Circular Strings Editorial by sounansya


\((x,l)\) に対し、\(C(x,l) > C(y,l)\) を満たす \(1\le y\le N\) の個数を求められれば良いです。

これは Trie 木を作ることで求めることができます。各 Trie 木のノードで現在そのノードまで同じ文字列がいくつあるか・そのノードが表す文字列と同じ長さの文字列で辞書順で真に小さい文字列がいくつあるか、を持ち計算することで全てまとめて \(\sigma = 26\) として \(O(\sigma N^2)\) で計算することができます。

実装例(Python3)

import sys

input = sys.stdin.readline
sys.setrecursionlimit(10**7)

n, q = map(int, input().split())
s = input().rstrip()
s += s
d = [[-1] * n for _ in range(n)]


def f(l, offset, idxs):
    if l == n:
        return
    if len(idxs) == 1:
        i = idxs[0]
        for j in range(l, n):
            d[i][j] = offset
        return
    g = [[] for _ in range(26)]
    for i in idxs:
        g[ord(s[i + l]) - ord("a")].append(i)
    for k in range(26):
        if len(g[k]) == 0:
            continue
        for i in g[k]:
            d[i][l] = offset
        f(l + 1, offset, g[k])
        offset += len(g[k])


f(0, 0, [i for i in range(n)])
for i in range(n):
    for j in range(n - 1):
        d[i][j + 1] += d[i][j]
idx = 0
for _ in range(q):
    a, l = map(int, input().split())
    idx = (idx + a) % n
    print(d[idx][l - 1])

posted:
last update: