首先,ac自動機,不是 自動accepted機,這是乙個多模字串匹配演算法,學習這個演算法,首先要熟悉kmp演算法這個單模字串匹配演算法,然後,我們知道有個高效的多模字串匹配演算法,叫字典樹,它處理的是一些單詞在乙個句子裡出現了幾次,但假如不是在乙個句子裡,而是在乙個字串裡呢?那它就顯得很弱了,所以,ac自動機出現了!
aho-corasick automaton,該演算法在2023年產生於貝爾實驗室,是著名的多模匹配演算法
先講一下ac自動機的工作流程吧:
1、以所有模式串構建一棵trie樹(字典樹)
2、構建每個節點的fail指標
3、與文字串進行匹配
第乙個流程就不用講了吧,就是字典樹的模板,重點講的是第二個流程——fail指標的構建,每個節點的fail指標,就好比kmp裡面模式串的next陣列,當這個點失配時,應該跳到哪個點繼續匹配,不一定是跳到這乙個單詞的前面,有可能會跳到別的單詞上,某個節點的fail指標構建的根據是:root到這個節點的路徑的所有字尾中,剛好是某個單詞的字首的字尾中的最長的那個,這樣說可能比較抽象,來看看下面這幅圖吧:
這是構建8號節點的fail指標時的樣子,可以發現,1到8的路徑的字尾分別是:cab、ab、b ,其中只有ab這個字尾剛好是某個單詞的字首,也就是ab這個單詞,於是,8的fail指標就指向3
那麼fail指標怎麼求呢?可以模擬一下kmp的next陣列是怎麼求的,在kmp演算法中,next[i]是由next[i-1]得到的,那麼同樣的,某個節點的fail指標也可以由它的父親節點得到,在kmp裡,我們使乙個j=next[i-1],當s[j+1]!=s[i]時,j=next[j],直到j=-1或s[j+1]=s[i],同樣的,在ac自動機裡面,我們還是讓j=tree[ree[i].fa].fail,並且加乙個c,讓c=i和i的father之間的邊上的字元,然後如果j沒有c這個兒子,j=tree[j].fail,直到j=-1或j有c這個兒子了,就讓i的fail指向j的c這個兒子,因為每乙個節點的fail都可能由層次比他淺的節點得到,所以我們需要用廣度優先搜尋,來遍歷每個點,如果還不理解,可以結合kmp演算法來想一下就好了
**如下:
void makefail()//注意要使tree[0].fail=-1,和kmp裡面讓next[0]=-1是乙個道理
}
那麼匹配起來就很容易了,我們以洛谷上的一道模板題作為例子,那麼我們建樹**如下:
void build(char ss,int z)
else//如果匹配成功
if(ans==n)break;//小優化,已經找到全部單詞就退出
}
完整的**:
#include #include struct node
}tree[1000010];
int n,len=0;
char s[1000010];
bool v[1000010];
int ch(char x)
void build(char ss,int z)
}char wbc[1000010];
int main()
tree[0].fail=-1;
makefail();
int i=1,j=0,ans=0;
scanf("%s",wbc+1);
int m=strlen(wbc+1);
memset(v,false,sizeof(v));
while(i<=m)
else
if(ans==n)break;
}printf("%d",ans);
}
update on 2020.6.17:寫了個更順眼的版本:
#include #include #include #define maxn 1000010
int n; char s[maxn];
struct node
}*root=new node(null);
void ins(int len)
node *q[maxn];int st=1,ed=0;
void makefail() }}
int main()
else now=now->next[s[i++]-'a'],now->mat=1;
} int ans=0;for(int i=ed;i>=1;i--)
q[i]->fail->mat|=q[i]->mat,ans+=q[i]->mat*q[i]->end;
printf("%d",ans);
}
AC自動機詳解
最近真是太頹了,做了一堆板子題,現在對一些知識點順便來個總結記錄 大家應該都知道kmp和trie樹吧,不懂的可以看我部落格或到網上自己動手尋找資料。ac自動機是乙個很好的東西,這是因為它的名字很好它能夠在有多個模式串的時候進行全文匹配,這十分方便地擴充套件了kmp的功能,實際上它的思路與原理與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...
AC自動機詳解
首先,看清楚了,這是ac自動機不是自動ac機 引用ac自動機模板題上的一句話 ovo在學習ac自動機之前,應該先掌握一下兩個前置技能 ac自動機,通俗地講,就是在trie上跑kmp。ac自動機利用trie的性質和kmp的思想,可以實現字串的多模匹配。kmp是單模匹配,而它與ac自動機最大的區別就在f...