Lyndon 分解
Lyndon 串
其嚴格最小字尾為其本身的串,稱為 \(Lyndon\) 串,也就是 \(s\) 是其所有迴圈移位中嚴格最小的。
\(s,t\) 都為 \(Lyndon\) 串是,且 \(s<t\),則 \(st\) 也為 \(Lyndon\) 串。證明 \(t>st\) 後即可證明該性質。
Lyndon 分解
\(Lyndon\) 分解為將 \(s\) 分解得 \(s=s_1s_2s_3 \dots s_k\),且 \(s_i \geqslant s_{i+1}\),\(Lyndon\) 分解是存在且唯一的。
存在性由 \(Lyndon\) 串的性質不難得到,唯一性可以用反證法來證明。
Duval 演算法
\(Duval\) 演算法可以 \(O(n)\) 求出一個串的 \(Lyndon\) 分解。
對於字串 \(s\) 和字元 \(c\),若 \(sc\) 是某個 \(Lyndon\) 串的字首,則對於字元 \(d>c\) 有 \(sd\) 是 \(Lyndon\) 串。
維護三個指標 \(p,i,j\)。\([1,p-1]\) 是已經進行完 \(Lyndon\) 分解的部分,\([p,j-1]\) 為 \(s_1s_2s_3 \dots s_kt\),其中 \(t\) 可以為空串,且 \(s_1\) 是 \(Lyndon\) 串和 \(s_1=s_2= \dots =s_k\)
當前加入字元 \(s_j\),令 \(i=j-|s_1|\),即為 \(t\) 在迴圈串對應的位置。進行分類討論:
當 \(s_i=s_j\) 時,\(t\) 能繼續匹配,讓 \(i,j\) 都向後移動一個位置。
當 \(s_i<s_j\) 時,得 \(s[p,j]\) 為 \(Lyndon\) 串,將 \(i\) 移動到 \(p\),\(j\) 向後移動一個位置。
當 \(s_i>s_j\) 時,得 \(s_1s_2s_3 \dots s_k\) 為分解後的串,然後繼續考慮 \(t\)
因為 \(p\) 只向後移動,\(j\) 向前移動的距離不超過 \(p\) 向後移動的距離,所以複雜度為 \(O(n)\)。
while(p<=n)
{
int i=p,j=p+1;
while(j<=n&&s[i]<=s[j]) i=s[i]==s[j++]?i+1:p;
while(p<=i) p+=j-i,ans^=p-1;
}
這段程式碼求的是 \(Lyndon\) 分解所有右端點的異或和。
應用
求解最小迴圈表示,\(O(n)\) 對所有 \(s[1,i]\) 求最小最大字尾。