參考資料
hihocoder1441
hihocoder1445
史上最通俗的字尾自動機詳解
練習題hihocoder1449
hihocoder1457
hihocoder1465
hihocoder1413 筆記
字串 aab
模板
struct suffixautomaton
int q=ch[p]
[c];
if(len[p]+1
==len[q]
)int nq=
++cnt;
memcpy
(ch[nq]
,ch[q]
,sizeof ch[q]);
len[nq]
=len[p]+1
; fa[nq]
=fa[q]
; fa[q]
=fa[np]
=nq;
for(
;ch[p]
[c]==q;p=fa[p]
) ch[p]
[c]=nq;
}//t==0表示相同子串不重複計算,t==1表示重複計算
void
work()}};
dag上dp
確定遍歷順序,陣列 a 為結點遍歷順序
for
(int i=
1;i<=node;i++
) t[len[i]]++
;for
(int i=
1;i<=node;i++
) t[i]
+=t[i-1]
;for
(int i=
1;i<=node;i++
) a[t[len[i]]--
]=i;
乙個結點出發的不同子串個數
對於乙個節點 i
ii,f[i
]f[i]
f[i]
表示從 i
ii 出發的子串個數(不含空串)。那麼, f[i
]f[i]
f[i]
就等於∑(i
,j)∈
edge
(f[j
]+1)
\sum_(f[j]+1)
∑(i,j)
∈edg
e(f
[j]+
1),f [1
]f[1]
f[1]
即是答案。
轉移順序的話,就按照 a
aa 的倒序
for
(int i=cnt;i>=
1;i--
)for
(int j=
0;j<
26;j++)if
(ch[a[i]
][j]
) f[a[i]]+
=f[ch[a[i]
][j]]+
1;
乙個子串出現的次數等於其所在狀態的 end
posendpos
endpos
的大小
size[np]=1
;for
(int i=cnt;i;i--
) size[fa[a[i]]]
+=size[a[i]
];
乙個狀態所包含的子串的數量for
(int i=
1;i<=cnt;i++
)for
(int j=
0;j<
26;j++)if
(ch[a[i]
][j]
) num[ch[a[i]
][j]]+
=num[a[i]
];
最長公共字首int u=
廣義字尾自動機
struct sam
else
else
}return np;
}void
init()
void
build()
}for
(int i=
1;i<=cnt;i++
)for
(int i=
1;i<=cnt;i++
)for
(int i=
1;i<=cnt;i++
)for
(int i=cnt;i>root;i--
) size[fa[a[i]]]
+= size[a[i]];}};
學習筆記 字尾自動機SAM
好抽象啊,早上看了兩個多小時才看懂,fading 早就懂了 講解就算了吧 可以去看看其他人的部落格 siz 為該串出現的次數,l 為子串長度,每次乘一下就好了 code below include define ll long long using namespace std const int m...
字尾自動機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被稱作初始狀態,由它能夠到達其餘所有狀態。自動機中的所有轉移 即有向邊 都被某種符號...