學習筆記 Lyndon Word

2022-05-04 20:36:08 字數 3137 閱讀 3506

若乙個字串\(s\)的最小字尾是它自己,我們稱其為\(lyndon\)串。

等價定義:若\(s\)是其所有迴圈重構串中字典序最小的串,則\(s\)是\(lyndon\)串。

任意字串\(s\),都可以唯一分解成\(s=s_1s_2...s_k\),其中\(\forall s_i\)為\(lyndon\)串,且\(s_i≥s_\)

存在性證明

先來看乙個引理:

引理1:

如果\(u\),\(v\)都是\(lyndon\)串,並且字典序\(u,則\(uv\)也是\(lyndon\)串。

(感覺比較顯然吧,但還是證明一下

1.\(len(u)≥len(v)\)時

因為\(v>u\),所以\(v\)>\(uv\),又因為\(v\)是\(lyndon\)串,所以\(v\)的所有非自己的字尾都大於\(v\),所以開頭在\(v\)的部分的字尾都大於\(uv\)。因為\(u\)也是\(lyndon\)串,所以\(u\)的所有字尾都大於\(u\),\(uv\)的開頭在\(u\)部分的字尾也就大於\(uv\)(在\(u\)部分的比較就已經大於)

2.\(len(u)時

若\(u\)不是\(v\)的字首,那麼在\(len(u)\)之前就有\(v>u\),所以\(v>uv\),同上可證。

若\(u\)是\(v\)是的字首,那麼\(v>uv\),同上可證。

有了引理之後再來證明。

首先,\(s\)中的每乙個單個字元都是乙個\(lyndon\)串,初始時每段都只有乙個字元。

從左往右開始合併,左邊已經合併了的字串\(s_i\)大於當前字元\(s[j]\)的話就把\(s[j]\)併入\(s_i\),根據引理1可得這樣合併後分出來的每一段都是\(lyndon\)串。

而每次比較的時候\(s_i都並進去了,所以沒有並進去的話,就滿足每一段\(s_i>s_\)

唯一性證明

(其實這個也比較顯然吧,根據上面我們是能並就並了,沒有其他可操作的空間,所以就只有一種

這個我們用反證法。

假設對於乙個字串\(s\)有兩種\(lyndon\)分解

我們記第一次不同的位置為\(i\),設\(len(s_i)>len(s_')\)

設\(s_i=s_'s_'...s_'s_'[1...l]\)

\(s'_[1...l]\)指第\(k+1\)段串中的字首\(1..l\)

可以得到以下關係:

\(s_i:\(s_i\)是\(lyndon\)串,所以它的字尾大於它

\(s_』[1...l]≤s_』\):乙個字串的字首小於等於它自己

\(s_』≤s_i'\):\(lyndon\)分解中,前面的段的字典序大於後面的段的字典序。

\(s_i':\(s_i'\)是\(s_i\)的字首,乙個字串的字首小於等於它自己

綜合上述不等式,可以得到\(s_i,產生矛盾,所以假設不成立

是一種在\(o(n)\)時間複雜度之內求出乙個串的\(lyndon\)分解的演算法。

引理2:

若字串\(v\)和字元\(c\)滿足\(vc\)是某個\(lyndon\)串的字首,則對於字元\(d>c\)有\(vd\)是\(lyndon\)串。

(覺得還是可以感性理解

證明:設\(lyndon\)串為\(vct\)

根據\(lyndon\)串的性質可得,\(\forall i∈[2,len(v)],v[i...len(v)]ct≥vct\).

根據\(i\)的取值範圍,\(v[i.. .len(v)]\)長度最大是\(len(v)-1\),那麼\(v[i...len(v)]c\)的長度小於等於\(v\)。

所以\(v[ i...len(v)]c\)要麼是\(v\)的字首(\(v[i...len(v)]ct\)在\(t\)的部分大於\(vct\)),要麼大於\(v\),總之\(v[i..len(v)]c\)不可能小於\(v\),否則\(v[i...len(v)]ct≥vct\)是不會成立的。

所以可以得到:\(v[i...len(v)]c≥v\)

那麼:\(v[i...len]d>v[i...len]c>v\),所以\(v[i...len]>vd\)

演算法流程

在這個演算法中,我們維護三個變數\(i,j,k\)

其中,\(s[1...i-1]=s_1s_2...s_g\)是已經固定下來的分解,滿足每一段\(l∈[1,g-1],s_l>s_\)

\(s[i...k-1]=t^hv,h≥1\)是沒有固定的分解,並且\(t\)是\(lyndon\)串,\(v\)是\(t\)的乙個字首(可為空)。

\(j=k-|t|\),當前掃到未處理的字元是\(s[k]\)

分三類情況討論:

\(s[k]==s[j]\):繼續往前掃,保持週期

\(s[k]>s[j]\):根據引理2,我們將\(t^hvs[k]\)合併起來,是乙個\(lyndon\)串(是向前合併,\(t\)和\(vs[k]\)合併起來,再將\(tvs[k]\)與前面的\(t\)合併(注意相等的兩個串並不能用引理1進行合併,因為\(uu\)的字尾\(u\)不大於$uu $)。

這裡的合併是相當於把\(t^hvs[k]\)當成乙個新的\(t\),不是就把它當成\(lyndon\)分解裡的一段了,它還有可能和後面的串拼在一起形成乙個新的\(lyndon\)

\(s[k]:\(t^h\)的分解被固定為\(h\)個\(lyndon\)串,演算法從\(v\)的開頭重新開始。

複雜度分析

\(i\)只會往右移,\(k\)移動的距離不超過\(i\)右移的距離(\(k\)移動\(|v|\),而\(i\)移動\(|t^hv|\))

複雜度為\(o (n)\)

code view

#include#include#include#include#include#include#include#includeusing namespace std;

#define n 5000005

#define inf 0x3f3f3f3f

#define ll long long

int rd()

while(c>='0'&&c<='9')

return f*x;

}int n,ans;

char s[n];

int main()

while(i<=j)

}printf("%d\n",ans);

return 0;

}

Lyndon Word學習筆記

定義 對於字串 s 若 s 的最小字尾為其本身,那麼稱 s 為lyndon串 等價性 s 為lyndon串等價於 s 本身是其迴圈移位中最小的乙個 任意字串 s 都可以分解為 s s 1 s 2 dots s k 其中 forall s i 為lyndon串且 s i geqslant s 且這種分...

學習筆記 雜湊學習筆記

hash基本原理 hash就是乙個像函式一樣的東西,你放進去乙個值,它給你輸出來乙個值。輸出的值就是hash值。一般hash值會比原來的值更好儲存 更小 或比較。那字串hash就非常好理解了。就是把字串轉換成乙個整數的函式。而且要盡量做到使字串對應唯一的hash值。它的主要思路是選取恰當的進製,可以...

學習筆記 CentOS 學習筆記01

簡單的做個課堂筆記 虛擬機器用的是vmware,系統是centos cd etc sysconfig network scripts pwdls 顯示列表 cat ifcfg eth0 檢視檔案內容 vi ifcfg eth0 進入vi編輯器 onboot no 原始設定 x逐字刪除 d刪除整行 a...