給定一個字符串 S(長度 ≤ 100,000),將其視為環狀字符串,列出所有 n 個循環移位,按字典序排序,取每行最後一列字符拼接,即為加密結果(即 Burrows-Wheeler 變換 BWT)。
原串: JSOI07 循環移位: JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0 字典序排序: 07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J 最後一列: I 0 O 7 S J → "I0O7SJ"
BWT 的標準構建方法:
S 複製兩份拼接:T = S + S(長度 2n)T 構建後綴數組 SASA,若 SA[i] < n,說明該後綴對應一個合法的循環移位(起始位置在原串範圍內)T[SA[i] + n - 1](或 S[(SA[i] - 1 + n) % n])SA 順序收集這些字符即為答案// 構建 T = S + S
for (int i = 0; i < n; ++i) {
T[i] = T[i + n] = S[i] + 1; // +1 避免 0 干擾
}
T[2*n] = 0; // 結束符
// 後綴數組構建(倍增/SA-IS)
build_sa(2*n, 128); // 字符集大小
// 輸出 BWT
for (int i = 0; i < 2*n; ++i) {
if (SA[i] < n) {
int pos = (SA[i] - 1 + n) % n; // 循環前一字符
putchar(S[pos]);
}
}
T 的所有後綴中,起始位置 [0, n-1] 的恰好對應 S 的所有循環移位S[i...n-1] + S[0...i-1] 的最後一字符是 S[i-1](循環意義下)BWT 是可逆的(配合原串在排序矩陣中的行號),這是 bzip2 等壓縮算法的核心。本題僅需正向變換。