문제
문자열 \(s\) 안의 서로 다른 팰린드롬 부분 문자열은 최대 \(n\)개임이 알려져 있다(palindromic factor 한계). 팰린드롬 트리(eertree, palindromic tree)는 이 \(O(n)\) 개의 팰린드롬을 노드로 갖고, 온라인 \(O(n)\) 에 구성되며, 각 팰린드롬의 등장 횟수·길이 등을 일괄 계산한다.
두 개의 루트
eertree에는 특별한 가짜 루트 두 개가 있다.
- 길이 \(-1\) 루트(imaginary root): suffix link 사슬의 바닥.
- 길이 \(0\) 루트(empty string): 짝수 길이 팰린드롬의 시작점.
각 노드 \(v\) 는 한 팰린드롬을 나타내며 len(v)(길이), link(v)(가장 긴 진 팰린드롬 접미사로의 링크), 글자별 전이 next(v, c) 를 가진다. 전이 next(v,c) 는 "\(v\) 양옆에 글자 \(c\) 를 붙인 팰린드롬 \(c\,v\,c\)".
suffix link
link(v) 는 \(v\) 의 가장 긴 진(proper) 팰린드롬 접미사 노드를 가리킨다. 길이 \(-1\) 루트는 모든 길이 1 팰린드롬의 link 바닥 역할을 한다. 이 link들은 트리를 이루며, 등장 횟수 집계 등 트리 DP의 골격이 된다.
온라인 구성
글자를 하나씩 끝에 붙인다. 현재까지의 가장 긴 팰린드롬 접미사를 가리키는 last 에서 시작해, suffix link 사슬을 따라 올라가며 "\(s[i] \cdot (\text{후보}) \cdot s[i]\)" 가 팰린드롬이 되는 첫 후보 \(X\) 를 찾는다(즉 \(s[i - len(X) - 1] = s[i]\)). 그 자리에 새 팰린드롬 전이가 없으면 새 노드를 만들고, 그 노드의 suffix link 역시 \(X\) 의 link 사슬을 한 번 더 따라가 결정한다.
각 글자 추가에서 사슬을 따라 올라가는 총 횟수가 amortized \(O(1)\) (last의 깊이 증가/감소 논변)이라 전체 \(O(n)\).
핵심 사실
| 항목 | 값 |
|---|---|
| 노드 수 | \(\le n + 2\) (두 루트 포함) |
| 서로 다른 팰린드롬 수 | 노드 수 \(- 2\) |
| 각 팰린드롬 등장 횟수 | 생성 시 +1, link 사슬 따라 합산 |
| 가장 긴 회문 접미사 | 매 단계 last |