Palindrome Tree (Eertree) - Cây Xâu Đối Xứng¶
Tác giả: FPTOJ Team
Nội dung tham khảo từ: CP-Algorithms - Palindrome Tree
1. Bản chất vấn đề¶
Bài toán: Đếm số palindrome con phân biệt¶
Cho xâu \(S\) độ dài \(N\). Đếm số xâu con palindrome phân biệt trong \(S\).
Cách thường: Duyệt tất cả \(O(N^2)\) xâu con, kiểm tra palindrome \(O(N)\) mỗi xâu \(\Rightarrow O(N^3)\).
Palindrome Tree (Eertree): Xây dựng trong \(O(N)\), mỗi palindrome là 1 nút trong cây.
So sánh¶
| Phương pháp | Thời gian | Không gian |
|---|---|---|
| Duyệt + Manacher | \(O(N^2)\) | \(O(N)\) |
| Hashing | \(O(N^2)\) | \(O(N^2)\) |
| Palindrome Tree | \(O(N)\) | \(O(N)\) |
2. Tư duy cốt lõi¶
Cấu trúc cây¶
Palindrome Tree có 2 gốc:
- Node \(-1\): Gốc ảo (độ dài \(-1\)),方便处理 lẻ palindrome.
- Node \(0\): Gốc cho chẵn palindrome (độ dài \(0\)).
Mỗi nút đại diện cho 1 palindrome duy nhất. Cạnh \(c\) từ node \(u\) đến node \(v\) nghĩa là: palindrome \(v\) = \(c\) + palindrome \(u\) + \(c\).
Mỗi nút lưu:
len: độ dài palindromelink: suffix link (palindrome đối xứng dài nhất là hậu tố đúng của palindrome hiện tại)next[c]: palindrome con khi thêm ký tự \(c\) vào 2 đầu
Trace chi tiết¶
Xâu: \(S = \text{"abacaba"}\)
| Bước | Ký tự | Palindrome mới tạo | Độ dài | Suffix link |
|---|---|---|---|---|
| 0 | \(a\) | \(a\) | 1 | → node 0 (rỗng) |
| 1 | \(b\) | \(b\) | 1 | → node 0 |
| 2 | \(a\) | \(aba\) | 3 | → node \(a\) |
| 3 | \(c\) | \(c\) | 1 | → node 0 |
| 4 | \(a\) | \(aca\) | 3 | → node \(a\) |
| 5 | \(b\) | \(bacab\) | 5 | → node \(b\) |
| 6 | \(a\) | \(abacaba\) | 7 | → node \(aba\) |
Tổng palindrome phân biệt: \(\{a, b, c, aba, aca, bacab, abacaba\}\) = 7.
Suffix Link¶
Suffix link của node \(u\) là palindrome đối xứng dài nhất đúng là hậu tố của palindrome \(u\).
Ví dụ: suffix link của \(abacaba\) → \(aba\) (vì \(aba\) là hậu tố đúng của \(abacaba\) và là palindrome).
flowchart LR
N1["a (len=1)"] --> R0["rỗng (len=0)"]
N2["b (len=1)"] --> R0
N3["aba (len=3)"] --> N1
N4["c (len=1)"] --> R0
N5["aca (len=3)"] --> N1
N6["bacab (len=5)"] --> N2
N7["abacaba (len=7)"] --> N3
3. Phân tích tính đúng đắn¶
Tại sao mỗi nút là palindrome duy nhất?¶
Khi thêm ký tự \(c\) vào 2 đầu palindrome \(P\), ta được palindrome \(cPc\). Nếu \(cPc\) chưa tồn tại trong cây, tạo nút mới.
Suffix link đảm bảo mỗi palindrome chỉ được tạo đúng 1 lần.
Tại sao suffix link tạo cây?¶
Suffix link của palindrome \(P\) luôn ngắn hơn \(P\) (trừ node gốc). Do đó, suffix link tạo thành cây có gốc là node \(0\) (palindrome rỗng).
4. Đánh giá độ phức tạp¶
| Thao tác | Thời gian | Không gian |
|---|---|---|
| Xây Palindrome Tree | \(O(N)\) | $O(N \cdot |
| Đếm palindrome phân biệt | \(O(N)\) | \(O(1)\) |
| Số palindrome kết thúc tại vị trí \(i\) | \(O(1)\) mỗi vị trí | \(O(1)\) |
\(|\Sigma|\) = kích thước bảng chữ cái.