首先,看清楚了,這是ac自動機不是自動ac機
引用ac自動機模板題上的一句話:
ovo在學習ac自動機之前,應該先掌握一下兩個前置技能:
ac自動機,通俗地講,就是在trie上跑kmp。ac自動機利用trie的性質和kmp的思想,可以實現字串的多模匹配。kmp是單模匹配,而它與ac自動機最大的區別就在fail指標的求法,其餘思想基本相同。
所謂多模匹配,即給出若干個模式串和乙個文字串,需要查詢這些模式串在文字串**現的情況。
ac自動機的操作分為三步:
一、建樹
既然是要利用trie,自然要先建立一棵trie了。本文以she,he,say,her,shr五個字串為例建立一棵trie:
其中,root為根節點,綠色節點表示該節點為某個單詞的結尾,也就是結尾標記。
ac自動機的建樹方法與trie完全相同,在這裡就不再贅述。
建樹**:
void add(string s)三、字串匹配字串匹配的思想與kmp基本相同,實現方式與trie上查詢字串類似。將文字串從頭到尾一位一位在trie上查詢,對於每乙個節點,若沒有被遍歷過,沿著它的fail指標走,直到根節點或乙個已遍歷過的點。對於路徑上的所有點,將答案加上它的結尾標記,即當前節點為幾個字串的結尾,然後將其結尾標記改為-1,以顯示其已遍歷過。//將與根相連的節點的fail指標指向根節點並將它們入隊
while(q.size())
else
ac[now].son[i]=ac[ac[now].fail].son[i];
}//重複第4、5步
}
還是以這個圖為例:
若文字串為yasherhs,則:
對於y,a,trie中沒有對應的路徑
對於s,h,e,在trie中可以沿著root-s-h-e這條路徑走到第四層節點e,答案加1,沿著其fail路徑向上可以走到第三層節點e,答案加1;
對於r,此時指標指向第四層節點e的兒子指向的節點,也就是其fail指標指向的第三層節點e,隨後指向右下角節點r,答案加1;
對於h,s,因為已經遍歷過了,因此不會再進行遍歷
為什麼走到乙個已遍歷過的點也要停止呢?因為若乙個節點已被遍歷,則沿著它的fail指標走直到根節點的這條路徑上的所有節點一定都被遍歷過了,若在走一遍則屬於浪費時間,因此直接停止即可。
字串匹配**:
int get()習題:ac[n];
void add(string s)
//輸入模式串並插入trie
ac[0].fail=0;//將根節點的fail指標指向自己,其實這步可以不要,因為預設就是0
build();//求fail指標
cin>>f;
cout<
AC自動機詳解
最近真是太頹了,做了一堆板子題,現在對一些知識點順便來個總結記錄 大家應該都知道kmp和trie樹吧,不懂的可以看我部落格或到網上自己動手尋找資料。ac自動機是乙個很好的東西,這是因為它的名字很好它能夠在有多個模式串的時候進行全文匹配,這十分方便地擴充套件了kmp的功能,實際上它的思路與原理與kmp...
AC自動機詳解
首先,ac自動機,不是 自動accepted機,這是乙個多模字串匹配演算法,學習這個演算法,首先要熟悉kmp演算法這個單模字串匹配演算法,然後,我們知道有個高效的多模字串匹配演算法,叫字典樹,它處理的是一些單詞在乙個句子裡出現了幾次,但假如不是在乙個句子裡,而是在乙個字串裡呢?那它就顯得很弱了,所以...
AC自動機詳解
include include include include include include include include using namespace std typedef long long ll const int maxn 2 1e6 9 int trie maxn 26 字典樹 i...