演算法 AC自動機

2021-07-25 08:52:25 字數 1626 閱讀 2696

這篇部落格拖了好久好久,真是尷尬,原因大概是我感覺很多東西,都是直覺,有種只可意會不可言傳的味道,想完全搞懂,但後來仔細想想,ac自動機好像本來就不是乙個非常非常確定的演算法,比如說,我該拿覺很多情況可以把演算法卡成n^2。所以拖了很久,醬紫。

先談談ac自動機是什麼。我們知道kmp,可以快速的對乙個字串,用乙個模板進行匹配。然而當我們有多個模板的時候,再去重複的使用kmp演算法就顯得不太合適了。所以我們找到了ac自動機。再簡單的考慮一下,ac自動機可以說,是在一棵tire樹上,掛上kmp的失敗指標即可。

我們給出tire樹部分的**。

void insert(char *s)

}gs[k]++;

}顯然這是非常非常常見的tire樹寫法,關於tire樹,可以參考我以前的部落格。

然後我們給出構造失敗指標的**。

void ac_match()}}

我們回憶一下kmp的演算法,我們在求出第i位的失敗指標的時候,只會用到,i前面的位置。所以同理,我那們在構造失敗指標的時候,我們通過寬度有限搜尋來進行構造,是再合適不過的了。這裡我們明確一下我的陣列的含義。dl,寬搜佇列。sz[i][j]i號結點的下一位j字母的序號。pt[i] i 號結點的失敗指標。我們來詳細的說明pt[i]的含義。pt[i],指我們在i點嘗試尋找他是否有兒子j的時候,如果尋找失敗,我們應該去嘗試pt[i]這個結點的兒子j。如果不理解,可以參考一下部落格

我們給出匹配的**。

void solve(char *s)}}

printf("%d\n",tot);

}這段匹配**是基於下面的hdu模板題而言,是求出,有多少模板串可以和目標串匹配。繼續明確一下陣列含義,gs[i]記錄以i號結點結束的單詞的個數。tot為匹配模板串的數量。mark[i]則保證了,所有可能達到匹配的位置都進行了一次考慮。

最後我覺得我應該說明關於**的一些邊界處理。比如我將0號結點的所有26個字母都設為1,避免了因為完全無法匹配無法停止while的情況。

在這裡推薦一道hdu的ac自動機的模板題,hdu2222

並且在此給出ac**。

#include

#include

#include

#include

#include

using namespace std;

queue dl;

int t,n,tot,sum;

bool mark[1000000];

int sz[1000000][30],gs[1000000],pt[1000000];

char tp[1200000];

void insert(char *s)

}gs[k]++;

}void ac_match()}}

void solve(char *s)}}

printf("%d\n",tot);

}int main()

for (int i = 1;i <= 26;i++) sz[0][i] = 1;

tot = 0,sum = 1;

scanf("%d",&n);

for (int i = 1;i <= n;i++)

ac_match();

scanf("%s",tp);

solve(tp);

}return 0;

}

AC自動機演算法

ac自動機簡介 首先簡要介紹一下ac自動機 aho corasickautomation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和kmp...

AC自動機演算法

ac自動機簡介 首先簡要介紹一下ac自動機 aho corasick automation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和km...

AC自動機演算法

簡而言之,就是在kmp演算法的思想上加上trie樹來實現的乙個適合多個模式串的匹配問題。kmp演算法時間複雜度優秀的原因是有乙個next陣列,也叫做失配指標陣列,使得匹配的時間複雜度嚴格o m n o m n o m n ac自動機也有這樣的陣列來在失配的時候去跳到相應應該去的地方。所以,ac自動機...