1. 程式人生 > >SAM-字尾自動機

SAM-字尾自動機

字尾自動機

毒液哥 Fudan University

引論

字尾自動機Suffix Automaton, SAM)是基於字尾匹配字尾資料結構中一種功能強大的資料結構。
作為一個能接受字串所有子串有限狀態自動機,字尾自動機構建的時空複雜度均只需要 O ( n )

O(n) , 其中 n n 為字串長度,且字符集大小 Σ \Sigma 為常數。
下文將會討論字尾自動機的基本定義和構造以及複雜度分析,並結合例題來分析其作為自動機以外的性質。

字尾自動機

定義

在字串領域中,一個自動機有如下構成:

  • 狀態
  • 轉移
  • 一個初始狀態
  • 至少一個接受狀態
  • 字符集

有限狀態自動機Finate-State Automaton, FSA)的狀態和轉移數均是有限的。
若將狀態視作點,將轉移視作有向邊,則FSA可以用一個有向圖表示。

FSA可以讀入一個字串並且,從初始狀態開始,依次沿著字串的每個字元在當前狀態的轉移,轉移到下一個狀態,並最終停留在一個狀態上。若該狀態是一個接受狀態,則稱這個字串可以被這個FSA所接受。而後綴自動機是由長度為 n

n 的字串 S S 構造的一個狀態數為 O ( n ) O(n) ,轉移數為 O ( n ) O(n) 的能接受 S S 所有子串的FSA.

考慮一個樸素的能接受 S S 的所有子串的FSA,對所有不同的子串都建立一個狀態,那麼轉移易得,且所有狀態均是接受狀態。

對於一個長度為 n n 的字串 S S , 我們作如下記號:

  • S i S_i 表示 S S 中從左往右數第 i i 個字元。
  • S i , j S_{i, j} 表示 S S 中以 S i S_i 開頭, S j S_j 結尾的子串。
  • P r e i Pre_i 表示以 S i S_i 結尾的 S S 的字首,即 S 1 , i S_{1, i}
  • S u f i Suf_i 表示以 S i S_i 開頭的 S S 的字尾,即 S i , n S_{i, n}
  • E n d i , j End_{i, j} 表示 S i , j S_{i, j} S S 中出現位置的結尾座標構成的集合。
  • E n d T End_T 表示 T T S S 中出現位置的結尾座標構成的集合。
  • A + B A + B 表示將字串(字元) A A 和字串(字元) B B 拼接在一起得到的字串。

根據定義我們可以得到如下性質1:對於 S S 的兩個子串 A ,   B A,\ B , 若 E n d A End_A E n d B End_B 有交集,則必有 E n d A E n d B End_A \subseteq End_B E n d B E n d A End_B \subseteq End_A , 不妨設 E n d A E n d B End_A \subseteq End_B ,則 B B A A 的一個字尾。

定義 E n d End 等價類:若兩個狀態(子串)的 E n d End 集合相等,則他們屬於同一個 E n d End 等價類

樸素的FSA中狀態數為 O ( n 2 ) O(n ^ 2) ,是我們無法接受的,因此必須考慮將某些狀態合併在一起。

若將一個 E n d End 等價類中的元素按長度遞減排序,則每個字串都是前一個的字尾。若其中的某個狀態無法轉移字元 c c ,因為等價類中所有字串的結尾均相同,且出現位置也都相同,該等價類中所有子串均無法轉移 c c ;同理,若某個狀態可以轉移字元 c c ,則該等價類中所有子串均可以轉移 c c . 我們發現,一個 E n d End 等價類中所有狀態的轉移是相同的。因此可以一個 E n d End 等價類合併成一個狀態。對於這樣一個狀態 x x ,我們定義合併之前最長的字串為 x m a x x_{max} , 最短的為 x m i n x_{min} , x m a x x_{max} 的長度為 L e n g t h ( x ) Length(x) .

定義 x x 的字尾連結:一個 L e n g t h ( y ) Length(y)最大 y y ,使得 E n d x E n d y End_x \subset End_y , 則 y y x x 的字尾連結,記為 L i n k ( x ) Link(x) . 由前述性質可得, y y 狀態中所有子串均是 x x 中任意子串的字尾。

性質2:在 x x 無法轉移字元 c c 時, L i n k ( x ) Link(x) 有可能轉移 c c ,因為

相關推薦

字串(tjoi2016,heoi2016,bzoj4556)(sam(字尾自動機)+線段樹合併+倍增+二分答案)

佳媛姐姐過生日的時候,她的小夥伴從某東上買了一個生日禮物。生日禮物放在一個神奇的箱子中。箱子外邊寫了 一個長為\(n\)的字串\(s\),和\(m\)個問題。佳媛姐姐必須正確回答這\(m\)個問題,才能開啟箱子拿到禮物,升職加薪,出任CE O,嫁給高富帥,走上人生巔峰。每個問題均有\(a,b,c,d\)四個引

SAM-字尾自動機

字尾自動機 毒液哥 Fudan University 引論 字尾自動機(Suffix Automaton, SAM)是基於字尾匹配的字尾資料結構中一種功能強大的資料結構。 作為一個能接受字串所有子串的有限狀態自動機,字尾自動機構建的時空複雜度均只需要

SAM(字尾自動機)專題總結

這是一篇其實理解並不深刻只會打板子的蒟蒻寫出的總結 分成幾個板塊吧。。。。。。 1.檢查字串是否出現   給一個文字串 \(T\) 和多個模式串 \(P\),我們要檢查字串 \(P\) 是否作為 \(T\) 的一個子串出現。   對 \(T\) 建出 \(SAM\)   直接在後綴樹上從根開始往下走,

[Hihocoder](1445)字尾自動機二·重複旋律5 ----SAM構造

題目傳送門 做法: 我們知道SAM中 l[st] 陣列的意義是狀態st的最長子串的長度 從前一狀態到當前狀態的轉移所增加的子串數量: l[st] - l[slink[st]] AC程式碼: #inc

2018.12.15【SPOJ-LCS2】Longest Common Substring II(字尾自動機SAM

傳送門 解析: 這道題可以把所有串接在一起構建字尾自動機來做,但是那樣還不如寫字尾陣列。。。 所以這裡提供一個只有字尾自動機能實現的做法。 思路: 首先構建出第一個串的字尾自動機。 然後拿其他的串放到字尾自動機上面跑。同時更新答案。 程式碼裡面的

2018.12.15【SPOJ-LCS】Longest Common Substring(字尾自動機SAM

傳送門 解析: 小聲BB:vjudge上面應該出了一點問題,C++會Language Erro,C++14就沒有問題。 思路: 建立其中一個串的SAM,然後拿另外一個串去匹配,能夠匹配到的最大長度就是最長公共子串。 啊你問我為什麼這樣是對的,請回去重新學習什麼是

2018.12.15【HDU4622】Reincarnation(字尾自動機SAM

傳送門 解析: SAM基礎操作。 解析: 其實不管其他的單獨看字尾連結,即 f a

【模板】字尾自動機SAM

參考題目:洛谷P3804 解析: 其實這個東西的理解的話,說難沒有那麼難,說簡單也不是很簡單。 這裡先貼一個程式碼,什麼時候再更新吧。 程式碼: #include<bits/stdc++.h> using namespace std; #defin

字尾自動機】【SAM】學習相關以及模板

 這是一篇偷懶的文章,主要是今天確實碰到了比較難理解的資料結構。  之前是以為所有的字尾自動機都可以用字尾陣列代替的,今天做到有一道題hdu6405,似乎並非如此了,主要這題是多串的,所以沒法子字尾陣列,只能字尾自動機(而且還是廣義字尾自動機,相關題解明天補上)  今天參考的博文 傳送門A

字尾自動機】【SAM】【自動機】【資料結構】字尾自動機理解(入門)

引入 來吧字尾自動機 我們先來看一看字尾陣列可以幹一些什麼事情 1.可以檢視當前字尾在所有後綴的排名 2.可以看最大的相同子串 但是缺點呢卻也非常的明顯——顯然這tm是個靜態的。。。。 於是只好另闢蹊徑——字尾自動機 我們來看看字尾自動機可以幹一些什

字尾自動機(SAM)速成手冊!

正好寫這個部落格和我的某個別的需求重合了。。。我就來講一講SAM啦qwq 字尾自動機,也就是SAM,是一種極其有用的處理字串的資料結構,可以用於處理幾乎任何有關於子串的問題,但以學起來異常困難著稱(在機房裡,最先學會SAM的永遠是大佬(比如litble和zyf(他在退役前就學了)))。 但是!!!當你學了

SPOJ 1811. Longest Common Substring (LCS,兩個字串的最長公共子串, 字尾自動機SAM

/* *********************************************** Author :kuangbin Created Time :2013-9-8 23:27:46 File Name :F:\2013ACM練習\專

Codeforces Round #146 (Div. 1) C - Cyclical Quest 字尾自動機+最小迴圈節

#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #defin

【BZOJ4566】找相同字元【字尾自動機

題意  給定兩個字串,求兩個字串相同子串的方案數。 分析  那麼將字串s1建SAM,然後對於s2的每個字首,都在SAM中找出來,並且計數就行。  我一開始的做法是,建一個u和len,順著s2跑SAM,當st[u].next[c]存在的時候,u=st[u].next[c],

MemSQL Start[c]UP 2.0 - Round 1 E - Three strings 廣義字尾自動機

E - Three strings 將三個串加進去,看每個節點在三個串中分別出現了多少次。 #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk mak

洛谷P3804 字尾自動機

題目描述 給定一個只包含小寫字母的字串SS, 請你求出 SS 的所有出現次數不為 11 的子串的出現次數乘上該子串長度的最大值。 輸入輸出格式 輸入格式:   一行一個僅包含小寫字母的字串SS   輸出格

BZOJ 3998: [TJOI2015]弦論 字尾自動機

3998: [TJOI2015]弦論 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 4251  Solved: 1562 [Submit][Status][Di

Musical Theme(字尾自動機

Musical Theme Time Limit: 1000MS Memory Limit: 30000K 題目大意: 給定一個串,找出滿足條件最長子串: 1,長度大於等於5 2,至少出現兩次 3,至少有兩個出現位置不重疊 子串不一定要嚴格相等,兩兩差值相等即可。

[TJOI2015]弦論(字尾自動機

3998: [TJOI2015]弦論 Description 對於一個給定長度為N的字串,求它的第K小子串是什麼。 Input 第一行是一個僅由小寫英文字母構成的字串S 第二行為兩個整數T和K,T為0則表示不同位置的相同子串算作一個。T=1則表示不同位置的相同子串算作多

字尾自動機概述

如果對字尾自動機有一定了解,這幾篇文章對你可能會有些許幫助: menci’s字尾自動機學習筆記 字尾自動機學習指南 loj上的字尾自動機講解 一些題目 聽說對拆點講解很詳細 127~132周 以題目為主,當然也有一些講解。下面說一下我對字尾自動機的理解,不給出詳細證明。