再不更新這裡都長草了
ac自動機是乙個字串匹配演算法,與kmp的區別在於,ac自動機可以用\(o(\sum |s_i| + |s|)\)的複雜度在文字串中同時查詢多個模式串,例如這道題
對於初學者 就是我 而言,可以簡單地將ac自動機理解為kmp + trie樹,整個演算法分為三步:
將所有的模式串建成一顆trie樹
求出trie樹上每乙個節點的失配指標(fail)(類似kmp的next)
將文字串在trie樹上進行匹配
這一步和普通的字典樹一樣,不解釋
void insert(string& s)
p = t[p][s[i] - 'a'];
} num[p]++;
}
\(fail_u\)的定義為,tire樹內所有字串的所有字首中,字尾匹配長度最大的的位置;如下圖中,\(fail_i = j\)
(圖中不同顏色的邊代表字元)
如圖,節點\(i\)與節點\(j\)的字尾匹配最長,所以\(fail_i = j\)
如圖,\(fail_i = j\),則\(i\)的粉色子節點(此處用顏色表示字元)必然也與\(j\)的粉色子節點有最長的字尾,因此該子節點的\(fail\)指標就是\(k\)
具體求法:對於\(u\)的子節點\(v\),其\(fail\)指標為\(u\)的\(fail\)指標的字元與\(v\)相同的子節點,證明很簡單,因為\(fail_u\)與\(u\)的字尾匹配最長,而\(v\)節點上的字元\(i\)顯然與\(trie[fail_u][i]\)上的字元\(i\)相同,所以\(fail_v = trie[fail_u][i]\)
理解原理後我們很容易就能求出所有的\(fail\)指標:在字典樹上跑一遍bfs,根節點的子節點的\(fail\)指標顯然為0,所以先將這些點放入佇列;
對於每乙個當前搜尋到的節點\(u\),它的\(fail\)指標肯定已經被求出,所以我們只需要列舉它的所有子節點t[u][i]
,建立\(fail\)指標fail[t[u][i]] = t[fail[u]][i]
**如下:
void getfail()
} while(!q.empty()) else
} }}
這一部分理解難度不大,看**注釋即可:
int query(string s)
} return res;
}
用\(p\)表示將字串在\(trie\)樹上匹配時的位置,在每一輪迴圈中以\(p\)為起點向上跳,尋找匹配即可
trie樹的大小為\(\sum |s_i|\),建立\(fail\)指標的複雜度與其相同,遍歷文字串需要\(o(|s|)\),總時間複雜度為\(o(\sum |s_i| + |s|)\)
ac 自動機 - oi wiki
AC自動機 學習筆記
是一種數學模型,大概就是由一堆狀態和狀態轉移規則等東西構成,能與外界交換資訊,並改變動作。這個是理論上的東西,了解就行,對ac自動機的理解沒有大影響。通俗的講就是在trie上做kmp,處理多模式串匹配問題。trie 的每個結點就是乙個狀態,根結點是初始狀態。ac自動機的行為被定義為一下3個函式 1....
AC自動機學習筆記
ac自動機是基於字典樹和fail指標來快速一類解決多串匹配的問題。先用所有模式串建乙個字典樹。然後用bfs搞出每個節點的fail指標。fail指標是指向 和當前 字首的字尾有最長匹配的字首。洛谷3808 掃文字串的時候,標記一下訪問過的字典樹上的節點。include using namespace ...
AC自動機學習筆記
title ac自動機學習筆記 date 2020 08 31 15 53 40 tags 8月的最後一天,還是完成了ac自動機的學習。在熟練掌握了kmp後,我發現ac自動機並沒有想象的那麼難,既不難理解,也不難實現,於是決定寫點東西記錄一下。本篇主要談談ac自動機的理論,思想。首先我們必須要明確乙...