字尾自動機

2022-05-26 18:54:09 字數 1926 閱讀 3520

一、sam的性質:

sam是個狀態機。乙個起點,若干終點。原串的所有子串和從sam起點開始的所有路徑一一對應,不重不漏。所以終點就是包含字尾的點。

每個點包含若干子串,每個子串都一一對應一條從起點到該點的路徑。且這些子串一定是裡面最長子串的連續字尾。

sam問題中經常考慮兩種邊:

(1) 普通邊,類似於trie。表示在某個狀態所表示的所有子串的後面新增乙個字元。

(2) link、father。表示將某個狀態所表示的最短子串的首字母刪除。這類邊構成一棵樹。

二、sam的構造思路

endpos(s):子串s所有出現的位置(尾字母下標)集合。sam中的每個狀態都一一對應乙個endpos的等價類。

endpos的性質:

(1) 令 s1,s2 為 s 的兩個子串 ,不妨設 |s1|≤|s2| (我們用 |s| 表示 s 的長度 ,此處等價於 s1 不長於 s2 )。則 s1 是 s2 的字尾當且僅當 endpos(s1)⊇endpos(s2) ,s1 不是 s2 的字尾當且僅當 endpos(s1)∩endpos(s2)=∅ 。

(2) 兩個不同子串的endpos,要麼有包含關係,要麼沒有交集。

(3) 兩個子串的endpos相同,那麼短串為長串的字尾。

(4) 對於乙個狀態 st ,以及任意的 longest(st) 的字尾 s ,如果 s 的長度滿足:|shortest(st)|≤|s|≤|longsest(st)| ,那麼 s∈substrings(st) 。

sam的應用

1可以將其看作一字串的hash表,用於查詢

2求該字串的不同子串的數量

//每乙個點包括的字串集合

3求某一子串在該改串的出現次數->劃分endpos,遞迴的找

給定乙個長度為 n

'>

n 的只包含小寫字母的字串 s

'>

s。對於所有 s

'>s

的出現次數不為 1

'>1

的子串,設其 val

ue'>value

值為該子串出現的次數 ×

'>

× 該子串的長度。

請計算,val

ue'>value

的最大值是多少。

輸入格式

共一行,包含乙個由 n

'>n

個小寫字母構成的字串。

輸出格式

共一行,輸出乙個整數,表示答案。

資料範圍1≤

n≤106

'>1≤n≤1e6

保證至少存在乙個子串出現次數大於 1

'>1

1。輸入樣例:

aabab

輸出樣例:
4

#include #include 

#include

using

namespace

std;

typedef

long

long

ll;const

int n = 2000010

;int tot = 1, last = 1

;struct

node

node[n];

char

str[n];

ll f[n], ans;

inth[n], e[n], ne[n], idx;

void extend(int

c) }

}void add(int a, int

b)void dfs(int

u)

if (f[u] > 1) ans = max(ans, f[u] *node[u].len);

}int

main()

字尾自動機

基礎知識 step i 表示的是字串i在原字串中的位置。pareint i 表示root到parent i 的子串是root到i的最長字尾。字尾自動機遍歷可以得到原字串的所有子串。特殊技巧 一 字尾自動機的不同子串數有兩種求法 1.ans step i step parent i 1 i cnt 2...

字尾自動機

常用於處理字串問題,可以高效解決許多字串問題。有點像將乙個字串的所有字尾都建在乙個ac自動機上,但不同的是字尾自動機的節點數最多為2 n,因為它只記錄需要記錄的點,一些沒有記錄東西的點可以視為與下面有價值的節點並在一起,這樣大大降低了時間複雜度和空間複雜度。對於每乙個節點記錄它的後面加上每個字元後字...

字尾自動機

基礎學習 簡潔明瞭的講解 總狀態數不超過2n 12n 1 2n 1 包括初始狀態 統計每個end po sendpos endpos 等價類出現位置數量時,要按長度從長到短的計算cnt cntcn t。那為什麼一定要從長到短呢?比如回文自動機就直接是按照節點編號從大到小計算cnt cntcn t 罪...