字尾樹與字尾自動機

2021-07-14 20:23:55 字數 1993 閱讀 3327

先學習的是字尾樹向的字尾自動機qaq

介紹字尾樹的定義:

把所有字尾插到trie裡

然而實際上是插到trie裡之後再壓縮掉一些邊,這樣就是字尾樹了。

但我們發現如果乙個乙個找的話複雜度是o(

n2)

我們考慮倒著建立字尾樹,即:

串s = a+

s′那麼我們先建立s′

的字尾樹,然後建立a+

s′的字尾樹。

這樣的話我們每次只會在字尾樹裡面加入乙個新的字尾。

然後我們引入一些定義:

首先,對於字尾樹中的每個節點x,我們到根的那條路徑一定代表了乙個字串s。 de

px表示當前節點x的深度。 tr

ans(

ch) 擁有ch

+s這個字串作為字首的深度最淺的節點。

更簡易的,我們可以定義tr

ans(

ch) 表示當前節點

這樣的話我們可以考慮怎麼建立一棵字尾樹:

演算法流程:

如果我們已經建好了

s 的字尾樹,我們要建立x+

s的字尾樹。

我們新加入的這個串的節點規定為

p 。

考慮字尾樹中表示字串

s的節點是

u ,那麼我們知道tr

ans(

x)在u

處必然為空。

我們考慮往上跳到

u的某個祖先

w ,使得:tr

ans(

x)!=

null

這個也就意味著什麼呢? 設w

所代表的字串為s′

,那麼我們知道x+

s′會到達

w 的tr

ans(

x)處。 假如

w 的tr

ans(

x)是q

。我們找到了

q,並且找到了v=

parq

。 現在問題考慮兩點: 1.s

q == 1+

sw那麼我們就可以直接把x+

s 的剩餘部分掛到下面。 2.s

q > 1+

sw(即sq

的某乙個字首是x+

sw)

那麼我們就要:

①找到1+s

w 在v−

>

q 之間的那個位置。

②把邊拆成v−

>r,

r−>p,

r−>q

結束。字尾樹的構造偽**:

n = strlen(s);

now = root = new_node,len = 0;

for i:= n downto 1:

x = s[i];

w = now,now = new_node;

len = n - i + 1;

while(w != null && w -> trans[x] == null):

w -> trans[x] = now;

w = w -> father;

if w == null:

then

now -> fa = root;

else:

q = w -> trans[x];

if q -> len == w -> len + 1:

then

now -> fa = q;

else:

r = new_node;

r -> len = w -> len + 1;

r -> q,r -> now;

q -> fa = r,now -> fa = r;

while(w != null && w -> trans[x] == q):

w -> trans[x] = r;

w = w -> fa;

感覺上大致意思應該是對的,到時候補題+更改**。

佔字尾自動機的坑qaq

字尾自動機轉字尾樹模板

終於找到教程了,現在來寫一發 題目 jzoj4072 bzoj3998 弦論 第一問 其實非常好寫,連空間都不需要多開一倍,只需要sa陣列rank陣列和height陣列就好了,dfs一次可以求出 include include include include define n 1000010 usi...

字尾自動機

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

字尾自動機

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