1. 程式人生 > >AC自動機 HDU2222

AC自動機 HDU2222

for 一個 tor 自動機 聽說 names stdlib.h rgb std

學了KMP算法,就能解決大部分的單模匹配,但是當有多個搜索詞的時候就捉襟見肘了。然後就又有一個新知識(對我來說),AC自動機。

之前也聽說過,但是看到這個東西排在lrj的書的後面,我就被嚇到了,所以還是說不能害怕做題,要敢於正視問題,才能解決問題。

和KMP類似,AC自動機放在字典樹的基礎上,增加了類似KMP的next數組的東西,裏面叫做失敗指針,當然好像kmp那個next也叫失敗數組。。。

原理詳解: 點擊

不過我覺的還是要結合題來看比較好理解,還沒有用數組的映射實現過,只是用了指針(還寫了兩遍Orz,學完後還有昨天),有空把數組的學會補上 Mark

題意:給定字典,多個單詞

再給一個句子,問字典中有多少個單詞再句子中出現過。改造可以在字典樹的裏面增加元素(字符串,字符串長度,標記等等)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
const int MAXN = 1e6 + 5;
struct Trip
{
    Trip* next[26];
    Trip* fail;
    int sum;
    Trip()
    {
        memset(next, 0, sizeof(next));
        fail = NULL;
        sum 
= 0; } }; string str; Trip *root; Trip *q[MAXN]; int cnt = 0; int n,t; void init() { root = new Trip(); } void Insert(string s) { Trip *p = root; int n = s.size(); for(int k = 0; k < n; k++) { int i = s[k] - a; if(p->next[i] == NULL) { p
->next[i] = new Trip(); } p = p->next[i]; } p->sum ++ ; } void build_fail_pointer() { int head = 0; int tail = 1; memset(q, 0, sizeof(q)); q[head] = root; while(head < tail) { Trip *p = q[head++]; for(int i = 0; i < 26; i++) { if(p->next[i] != NULL) { q[tail++] = p->next[i]; if(p == root) { p->next[i]->fail = root; } else { Trip *q = p->fail; if(q->next[i] != NULL) { p->next[i]->fail = q->next[i]; } else { while(q) { if(q->next[i] != NULL) { p->next[i]->fail = q->next[i]; break; } q = q->fail; } if(q == NULL) p->next[i]->fail = root; } } } } } } void ac_solve(string s) { Trip *p = root; int n = s.size(); for(int i = 0; i < n; i++) { int k = s[i] - a; while(p->next[k] == NULL && p != root) p = p->fail; p = p->next[k]; if(p == NULL) p = root; Trip* temp = p; while(temp != root) { if(temp->sum >= 0) { cnt += temp->sum; temp->sum = -1; } else break; temp = temp->fail; } } } int main() { std::ios_base::sync_with_stdio(false); cin>>t; while(t--) { cnt = 0; init(); cin>>n; while(n--) { cin>>str; Insert(str); } build_fail_pointer(); cin>>str; ac_solve(str); printf("%d\n", cnt); delete root; } return 0; }

AC自動機 HDU2222