省選專練(學習)字尾自動機SAM(超詳細)

2021-08-21 14:26:40 字數 1356 閱讀 4385

先談我對字尾自動機的理解:

這不完全正確,它可以識別所有子串,於是也可以識別所有字尾

錯誤字尾自動機極限時間複雜度是o(n*2-1)比sa和s tree優

然後是字尾自動機可以幹什麼:

什麼?你說把他轉成lis跑nlogn?

既最長公共子串。

所以不是lcs最長公共子串行。

然後建出了sam就好了

建的過程不難

幾個定義

有乙個小問題:

1 首先建立儲存當前字元

x的結點

np,找到之前最後乙個建立的結點

(因為它一定滿足性質②

),然後就不斷按

pre指標跳

(直到跳到有

x兒子的結點為止).

2在這個過程當中我們會便利到沒有

x兒子的節點,沒有

x兒子的節點很好處理,直接將這個點連線過去即可

3 情況1:

step[p]+1=step[q]。這意味著我們

p的下乙個節點就是

q,在狀態

p和狀態

q中沒有多餘狀態存在,所以如果

p對於當前串可以接受字尾,那麼

q對於新串也可以接受字尾,所以

pre[np]=q

即可。

4 step[p]這時

,只要把q的

son邊和

pre邊都

copy到nq

上,然後把nq的

pre改為p,再

把q和np

的pre

都改為nq.

兩個重要性質

1.right集合。也就是我們所說的:step。

這個是什麼?這表示符合這種字串的集合。

2.parent 樹

也就是pre所構成的樹。

我們利用parent樹對siz合併

已達到求每個子串個數的目的。

通常並不需要真正建樹,只需要用桶排個序就好了。

#includeusing namespace std;

const int n=2e6+10;

char s[n];

int c[n]={};//乙個桶,計數排序

int a[n]={};//

int ans;

struct suffix_autosa[n];

int last,cnt;

void insert(char c)

cout<

}}sam;

int main()

字尾自動機SAM

原理詳細的可以看史上最通俗的字尾自動機詳解 想看懂還是要花很久。實現 include include using namespace std const int maxn 2000010 struct node nodes maxn int las 1 tot 1 char st maxn void...

SAM 字尾自動機

好文 luogup3804 定義.對給定字串s的字尾自動機是乙個最小化確定有限狀態自動機,它能夠接收字串s的所有字尾。對給定字串s的字尾自動機是乙個最小化確定有限狀態自動機,它能夠接收字串s的所有字尾。某一狀態t 0被稱作初始狀態,由它能夠到達其餘所有狀態。自動機中的所有轉移 即有向邊 都被某種符號...

SAM 字尾自動機

這玩意還真的好玄學,看了半天,也就看了個大概吧 確實很妙 總算理解了parent樹,但是關於sam的dag的性質的證明並沒有看太懂,也沒有特別明白。update 又看了一會,原來是自己把定義搞錯了,字尾自動機其實是在滿足以下條件的最簡狀態,主要是難構造,掌握構造 就好了,證明就不管了c。條件如下 摘...