kmp演算法可以解決單個模式串比較的問題,如果模式串有多個,那麼kmp演算法的效率就不盡如人意了。
一種可行的辦法是ac自動機,解決多模式串匹配的問題。
ac自動機和kmp演算法的思想是相同的,就是跳過不必要的移動,直接到失配的位置所對應處。只是ac自動機是以trie(字典樹)為基礎的。
同kmp演算法類似,ac自動機的演算法過程大致如下:
1.計算trie樹中每個節點失配後直接指向的位置
2.主串匹配
不妨結合kmp演算法的next陣列考慮(由於trie樹中有next這個名稱,為避免重複,trie上用fail來表示失配後指向的位置,fail的作用和kmp演算法中的next是相同的作用),fail同樣應當表示「最長公共前字尾」,這樣才能跳過不必要的移動。不同的是,kmp是線性處理,而ac自動機需要的是在trie樹上。
不難發現,計算fail的方法如下:
在trie上從根節點開始bfs,根據bfs序來依次處理每乙個節點(為啥不是dfs呢?因為既然是最長公共前字尾,那麼每個節點的fail指向的節點深度應該小於自己,bfs的順序就可以保證)。對於節點x,從它的父親節點的fail節點開始,與kmp類似,一直往fail位置跳,直到當前節點的字元與x的字元相同。不難發現,這就是節點x所代表的字首的「最長公共前字尾」。特別的,如果沒有找到fail,就把節點x的fail賦成根節點(這樣就不會造成影響)。
void create_fail () }}
}
主串匹配的時候,與kmp類似,就一直往fail跳,直到找到匹配當前字元的位置,如果沒有就會隨fail回到根節點重新來。
int match()
}return ans ;
}
這裡用hdu2222模板給出完整**
#include
#include
#include
#include
#include
using
namespace
std ;
const
int maxn = 60 ;
char s[10010][maxn], pat[1000010] ;
struct node
} *h, *p, *q ;
int n, m, tot, len[10010] ;
void create_trie ( int x )
}p->tim ++ ;
}node *q[100010] ;
void create_fail () }}
}int match()
}return ans ;
}void check ( node* now )
int main()
for ( i = 1 ; i <= n ; i ++ )
create_trie(i) ;
create_fail() ;
scanf ( "%s", pat+1 ) ;
m = strlen(pat+1) ;
printf ( "%d\n", match() ) ;
}return
0 ;}
吐槽:幸好我先學了kmp,這樣ac自動機就沒那麼難了 AC自動機 建立nlogn個AC自動機
string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...
AC自動機及字尾自動機
ac自動機是一種基於trie樹的演算法,其本質和kmp上的處理很相似。trie樹結構 kmp轉移思路 ac自動機組要由三個部分組成 trie樹的建立 fail指標的匹配 對ac自動機的詢問 每次建立自動機會有一次初始化 ac自動機類 struct node node結構體 struct ac voi...
AC自動機演算法
ac自動機簡介 首先簡要介紹一下ac自動機 aho corasickautomation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和kmp...