SAM學習小記

2021-10-10 19:53:41 字數 3316 閱讀 6525

只是乙個小記,不是演算法詳解

參考資料

史上最通俗的字尾自動機詳解

廣義sam模板題解

簡單的,乙個有向無環圖,邊有字母,滿足起點開始的每一條路徑都是原串的乙個子串。

並且保證複雜度在o(n

)o(n)

o(n)

級別內的。

每乙個子串p

pp的end

pos(

p)

endpos(p)

endpos

(p)被定義為原串中所有出現子串p

pp的末尾位置集合。

e nd

po

sendpos

endpos

相同的子串被定義為乙個end

po

sendpos

endpos

類,可以證明任何乙個串的end

po

sendpos

endpos

類數量不會超過o(n

)o(n)

o(n)

級別。性質:

根據e nd

po

sendpos

endpos

的兩個性質我們可以構建一棵樹,其中對於兩個end

po

sendpos

endpos

類x ⊆y

x\subseteq y

x⊆y那麼就有一條邊x

−>

yx->y

x−>y。

性質:還有乙個最重要性質,就是par

ents

parents

parent

s裡的節點就是sam

samsa

m裡的節點

懶得搞圖,去看參考資料。

void

add(

int c)

}return

;}

如果乙個sam

samsa

m中我們要加入多個字串時我們應該怎麼辦,廣義sam

samsa

m離線做法:對於所有的字串我們先構造出一棵tri

etrie

trie

樹,然後每一次的las

tlast

last

就是它tri

etrie

triend

po

sendpos

endpos

類一定是有出現過的,我們可以像sam

samsa

m

ll ins

(ll c,ll last)

} ll np=

++cnt;len[np]

=len[p]+1

;for

(;p&&

!ch[p]

[c];p=fa[p]

)ch[p]

[c]=np;if(

!p)fa[np]=1

;else

}return np;

}

p3804-[模板]字尾自動機

給出乙個長度為n

nn的串,求乙個最大的子串長度乘上子串出現次數

在構造sam

samsa

m的時候統計每個end

po

sendpos

endpos

類包含了幾個end

po

sendpos

endpos

,這就是這個end

po

sendpos

endpos

類子串**現的次數,然後每個end

po

sendpos

endpos

類取最長的子串就好了(在構造時已經儲存了)。

對於每個end

po

sendpos

endpos

的集合如何統計,對於每個npnp

np,它都會有乙個字首i

ii作為這個end

po

sendpos

endpos

類,而在往下的過程中這個字首位置i

ii會丟失(因為再往下的末尾都是在i

ii之後,而沒有乙個在i

ii的字尾是在之後加入的)。也就是讓fnp

++

f_++

fnp​++

,然後按照長度從大到小讓ffa

x+=f

xf_+=f_

ffax​​

+=fx

​,因為乙個節點的父節點長度一定比子節點小。

p3975-[tjoi2015]弦論

求乙個字串第k

kk大的子串。

對於相同的子串算同乙個時,那麼其實就是求sam

samsa

m上字典序第k

kk大的路徑,處理出每乙個節點的後繼狀態直接跑即可。

對於相同的子串不算同乙個時,我們處理處每個節點的end

po

sendpos

endpos

集合大小,這就是這個end

po

sendpos

endpos

類中每個子串的出現次數。然後用這個處理後繼狀態直接跑即可。

sp1811-longest common substring

求兩個串的最長公共子串

我們先構建第乙個串的sam

samsa

m,然後用第二個串在第乙個串上跑,如果不能繼續跑下去那麼我們直接在par

en

tparent

parent

樹上往前跳就好了,因為在sam

samsa

m中pare

nt

parent

parent

樹的左右可以類似於acac

ac自動機中fai

lfail

fail

樹的定義。然後跳完了之後取len

+1

len+1

len+

1就好了。

p5341-[tjoi2019]甲苯先生和大中鋒的字串

求出現次數恰好為k

kk的字串**現次數最多的長度

因為對於乙個相同的end

po

sendpos

endpos

類中的字串都是長度連續且不同的,也就是[le

nfax

+1,l

enx]

[len_+1,len_x]

[lenfa

x​​+

1,le

nx​]

這個範圍內每乙個長度各有乙個字串,然後差分做就好了。

字尾自動機sam學習小記

顧名思義,字尾自動機就是可以識別原串所有字尾的自動機,最後回到達葉子狀態,同時也可以識別所有連續子串。線性。由構造方法可知點數是線性的。構出sam後除了主鏈,即代表原串的鏈,其他的邊要麼就是構成了乙個新的字尾,要麼就是連線若干條構成了乙個新的字尾的邊,形成乙個類似樹的結構,所以邊也是線性的。很多性質...

SAM 學習筆記

詳見 text 字串 s 的 text 是乙個接受 s 所有字尾的最小dfa 確定性有限自動機或確定性有限狀態自動機 其中,s 每個字尾均可用一條從初始狀態 t 到某個終止狀態的路徑構成。包含 s 的所有子串 從 t 開始的任意路徑都構成乙個子串,每個子串也對應某條路徑。但是到某個狀態的路徑可能不止...

學習筆記 SAM

不想學博弈論不想學 sa 不想學插頭 dp,學 lct 被 axdea d 飛了,那就來學 sam。sam 是字尾自動機,名義上是字尾,但實際上它能表示出乙個字串的所有不同子串。不同於你的 o n 2 列舉,sam 構造,節點和邊的數量也都是 o n 級別的。更具體的,sam 表現為一張 dag,每...