DOJ logoDOJ
問題
最近追加された問題保存した問題
カテゴリDLCコンテストグループチーム掲示板
ランキング
正解数ランキングストリークランキングDOJ Powerランキング
提出状況
問題募集ログイン新規登録
DOJ logoDOJ

OI形式のサブタスク採点、Eloレーティング、Discord認証を備えたオンラインジャッジです。

問題
問題一覧カテゴリ
コミュニティ
コンテストランキング掲示板お知らせ外部のコンテストを開催するガイド
アカウント
ログイン新規登録ジャッジ状態
ポリシー
利用規約DLCの利用規則プライバシーAPI 文書言語ランタイムコンテストの順位報酬レーティングとパフォーマンス
© 2026 DOJ
All rights reserved
解説

DA.DA.S

問題に戻る

解説

하나의 문자열 XXX가 정해져 있다고 하자. 왼쪽부터 읽으며 주어진 문자열 중 하나가 처음으로 끝나는 순간 그 부분 문자열을 고른다. 그 뒤에서는 방금 고른 부분 문자열의 오른쪽에 있는 문자들만 대상으로 같은 과정을 반복한다. 끝나는 위치가 가장 빠른 부분 문자열부터 고르는 이 방법으로 f(X)f(X)f(X)를 구할 수 있다.

이 과정을 아호 코라식 자동자로 표현하자. 주어진 문자열들을 트라이에 넣고 실패 링크와 각 문자에 대한 전이를 구한다. 어떤 상태에서 주어진 문자열이 끝나는지를 표시할 때는 그 상태 자체뿐 아니라 실패 링크를 따라 도달하는 상태도 확인해야 한다. 주어진 문자열이 하나라도 끝나면 참으로 표시하며, 같은 문자열이 여러 번 주어져도 표시를 중복해서 세지 않는다.

상태 uuu에서 문자 ccc를 읽은 직후의 상태가 참으로 표시되어 있다면 부분 문자열 하나를 선택하고 루트로 돌아간다. 그렇지 않으면 그 상태에 머문다. 각각의 문자 전이가 도착할 상태와, 선택한 개수가 111 증가하는지를 이 규칙으로 정한다. 루트로 돌아가는 것은 방금 선택한 부분 문자열까지 읽은 정보를 모두 버려 다음 선택과의 겹침을 막는 역할을 한다.

참으로 표시된 상태에는 머무르지 않으므로 행렬의 상태에서는 제외한다. 남은 상태 수를 KKK라 하고 000부터 K−1K-1K−1까지 번호를 붙이되, 루트 상태의 번호를 000으로 둔다.

이제 같은 길이의 모든 문자열을 한꺼번에 처리한다. aua_uau​를 상태 uuu에 도달한 문자열의 개수, zzz를 그 문자열들 전체의 선택 개수 합이라고 하자. Bu,vB_{u,v}B는 상태 에서 출발하여 위 규칙에 따라 상태 로 가는 문자의 개수이고, 는 부분 문자열을 하나 선택하게 만드는 문자의 개수이다. 문자를 하나 덧붙이면

av′=∑u=0K−1auBu,v,z′=26z+∑u=0K−1auhua'_v=\sum_{u=0}^{K-1}a_u B_{u,v},\qquad z'=26z+\sum_{u=0}^{K-1}a_u h_uav′​=

가 된다. 기존의 각 문자열은 문자를 덧붙이는 262626가지 방법으로 확장되므로, 이미 얻은 선택 개수의 합 zzz에도 262626을 곱한다.

따라서 행벡터 (a0,a1,…,aK−1,z)(a_0,a_1,\ldots,a_{K-1},z)(a0​,a1​,…,aK−에 곱할 전이 행렬을 만들 수 있다. 왼쪽 위 부분에는 를 넣고, 마지막 열의 처음 개 원소에는 를 넣는다. 마지막 행은 마지막 원소 을 제외하고 모두 이다.

빈 문자열에서는 루트에 도달하는 경우가 하나이고 선택한 부분 문자열이 없으므로 초기 벡터는 (1,0,…,0)(1,0,\ldots,0)(1,0,…,0)이다. 전이 행렬의 MMM제곱을 분할 정복으로 계산하여 초기 벡터에 곱한 뒤, 마지막 성분을 출력한다. 모든 계산은 998 244 353998\ 244\ 353998 244 353으로 나눈 나머지로 수행한다.

L=∑i=1N∣Si∣L=\sum_{i=1}^{N}|S_i|L=∑i=1N​∣Si​∣라 하면 자동자의 전체 상태 수는 L+ 이하이고, 참으로 표시된 상태가 적어도 하나 있으므로 이다. 시간 복잡도는 이고, 공간 복잡도는 이다.

증명

아직 선택하지 않은 문자열 구간에서 끝나는 위치가 가장 빠른 유효한 부분 문자열을 III라고 하자. 최대로 많은 부분 문자열을 고른 방법에서 가장 먼저 등장하는 부분 문자열을 JJJ라고 하자. III의 끝나는 위치는 JJJ의 끝나는 위치보다 오른쪽일 수 없다. 따라서 JJJ를 II로 바꾸어도 그 뒤에 선택된 부분 문자열들과 겹치지 않는다. 부터 선택하는 최적해가 존재하므로, 그 오른쪽 구간에서도 같은 논리를 반복하면 그리디가 최적임을 알 수 있다. 유효한 부분 문자열이 없을 때에는 둘 다 아무것도 고르지 않는다.

Solution written by GPT6

u,v
​
uuu
vvv
huh_uhu​
u=0
∑
K−1
​
au​
Bu,v​
,
z′
=
26z+
u=0∑K−1​au​hu​
1
​
,
z
)
(K+1)×(K+1)(K+1)\times(K+1)(K+1)×(K+1)
K×KK\times KK×K
BBB
KKK
huh_uhu​
262626
000
1L+1
L+1
K≤LK\leq LK≤L
O(26L+L3log⁡(M+1))O(26L+L^3\log(M+1))O(26L+L3log(M+1))
O(L2)O(L^2)O(L2)
I
III

아호 코라식 자동자의 상태는 마지막 선택 이후 읽은 문자열의 접미사 중 트라이의 접두사와 일치하는 가장 긴 것을 나타낸다. 실패 링크를 통해 끝나는 문자열도 표시하므로, 주어진 문자열이 현재 위치에서 끝나는 모든 경우를 발견한다. 처음 발견한 즉시 하나를 선택하고 루트로 돌아가면 앞서 설명한 그리디와 같은 순서로 선택한다. 한 위치에서 여러 문자열이 끝나더라도 하나만 고르며, 끝나는 위치가 같으므로 어느 것을 골라도 이후 선택 가능한 구간은 같다.

길이가 같은 모든 문자열에 대해 aua_uau​와 zzz가 정의대로 계산되어 있다고 가정하자. 각 문자열과 덧붙일 문자 하나의 쌍은 정확히 하나의 다음 문자열을 만들므로 av′a'_vav′​는 전이를 따라 문자열의 개수를 합한 값이다. 기존 선택 개수는 모든 확장에 그대로 포함되어 총 26z26z26z를 기여한다. 상태 uuu의 문자열마다 huh_uhu​개의 문자에서 선택 개수가 하나씩 늘어나므로 새롭게 더해지는 값은 ∑uauhu\sum_u a_u h_u∑u​au​hu​이다. 따라서 두 전이식은 다음 길이에서도 정의를 만족한다.

초기 벡터는 빈 문자열의 개수와 선택 개수를 정확히 나타낸다. 위 전이를 MMM번 적용한 벡터의 마지막 성분은 길이 MMM의 모든 문자열에서 그리디로 선택한 개수의 합이다. 그리디가 각 문자열의 f(X)f(X)f(X)를 구하므로 이 값이 원하는 정답이다.