字尾自動機sam學習小記

2021-07-31 16:20:13 字數 1895 閱讀 1123

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

能走到sam上同乙個節點的字串right集一定相同,乙個節點的right集即任意乙個能到達當前節點的字串的right集。

right集只有包含與被包含或無交集,當r相同時增大l,right集不會減小。即parent,就是最小的right集,包含當前right集。使當前right集合法的最大長度,可以發現,使當前right集合法的最小長度即fa的mx加1。考慮上乙個加入的字元所代表的點p,當前要加入的字元所代表的點np,新建一條p=>np的邊,mx[np]=mx[p]+1,這個比較顯然,其實就是當前字串的長度。

考慮找p的fa,找到第乙個由當前字元轉移的點q,類似於ac自動機跳fail,找到最大的right集包含當前的right集,且包含當前字元轉移的,對之前的點都連一條到np的邊。由連邊方式可以發現當前p的所有fa都一定有當前字元轉移的邊。

設p連出去的點為q,當mx[p]+1==mx[q]時可以發現q是由p直接轉移過來的,可以直接加上當前字元,把np的fa設為q即可。當mx[p]+1!=mx[q]時可以發現p到q之間經過了多於乙個字元,我們必須新建狀態來表示當前情況,設這個點為nq,可以發現nq的mx比q的mx小,即right集較大,而p的mx比nq的mx小,即right集較大。所以q是nq的子集,nq是q的子集,fa[q]=nq,fa[nq]=p,fa[np]=nq,mx[nq]=mx[p]+1>

同時我們要處理nq的轉移,可以發現q的轉移和nq一樣,而之前轉移到q的狀態就要先轉移到nq,這個很容易證明。至此我們就完成了sam的構造。sam的應用很靈活,體現在它自動機的特性和parent樹,還有right集的各種特性,具體的例子留坑待填。例題鏈結

#include

#include

#include

#define ll long long

#define ull unsigned long long

#define fo(i,j,k) for(int i=j;i<=k;i++)

#define fd(i,j,k) for(int i=j;i>=k;i--)

using namespace std;

int const mn=5

*1e5+9,mp=1e6+9,inf=1e9+7;

int t,k,n,pon,f[mp],g[mp],son[mp][26],fa[mp],mx[mp],du[mp],qu[mp];

char s[mn];

int main()

intq=son[p][s[i]];

if(mx[p]+1==mx[q])fa[np]=q;

else

p=np;

}fo(i,1,pon)du[fa[i]]++;

int he=0,ti=0;

fo(i,1,pon)if(!du[i])qu[++ti]=i;

while(he!=ti)

if(!t)fo(i,1,pon)f[i]=1;

fo(i,1,pon)g[i]=f[i];

fo(i,1,pon)fo(j,0,25)du[son[i][j]]++;

he=0,ti=0;

qu[++ti]=1;du[0]++;

while(he!=ti)

}fd(i,ti,1)fo(j,0,25)

int now=1;

if(k>g[1])

while(1)}}

return

0;}

字尾自動機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。條件如下 摘...