HDU 2222 Keywords Search(AC自动机)题解
题意:给出模式串,问你主串出现了几种模式串。
思1路:ac自动机模板题。参考q学姐:av6295004
ac自动机的基本原理就是在trie上建Fail值,这样我每次失配就去找当前的最长后缀去匹配,一直到完全失配为止,这样我就找遍了所有的模式串。
代码:
#include<set> #include<map> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 5e5 + 10; const int maxM = 1e6 + 10; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1e4 + 7; struct Aho{ struct state{ int next[26]; int fail, cnt; }node[maxn]; int size; queue<int> q; void init(){ for(int i = 0; i < maxn; i++){ memset(node[i].next, 0, sizeof(node[i].next)); node[i].fail = node[i].cnt = 0; } size = 1; while(!q.empty()) q.pop(); } void insert(char *s){ int len = strlen(s); int now = 0; for(int i = 0; i < len; i++){ char c = s[i]; if(node[now].next[c - 'a'] == 0) node[now].next[c - 'a'] = size++; now = node[now].next[c - 'a']; } node[now].cnt++; } void build(){ node[0].fail = -1; q.push(0); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < 26; i++){ if(node[u].next[i]){ if(u == 0) node[node[u].next[i]].fail = 0; else{ int v = node[u].fail; while(v != -1){ if(node[v].next[i]){ node[node[u].next[i]].fail = node[v].next[i]; break; } v = node[v].fail; } if(v == -1) node[node[u].next[i]].fail = 0; } q.push(node[u].next[i]); } } } } int get(int u){ //匹配规则 int ret = 0; while(u){ ret += node[u].cnt; node[u].cnt = 0; u = node[u].fail; } return ret; } int match(char *s){ int ret = 0, now = 0; int len = strlen(s); for(int i = 0; i < len; i++){ char c = s[i]; if(node[now].next[c - 'a']) now = node[now].next[c - 'a']; else{ int p = node[now].fail; while(p != -1 && node[p].next[c - 'a'] == 0){ p = node[p].fail; } if(p == -1) now = 0; else now = node[p].next[c - 'a']; } if(node[now].cnt){ ret += get(now); } } return ret; } }ac; char s[maxM]; int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); ac.init(); for(int i = 0; i < n; i++){ scanf("%s", s); ac.insert(s); } scanf("%s", s); ac.build(); printf("%d\n", ac.match(s)); } return 0; }