HDU 2222 Keywords Search [AC自动机]

http://acm.hdu.edu.cn/showproblem.php?pid=2222
题意:给一堆模式串和一个文本串,问有多少个模式串在文本串中出现过。

AC自动机,在统计答案的时候记得将end清零就好

#include<queue>
#include<cassert>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
#include<map>
using namespace std;
#define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
#define dep(i,f,t) for(int i = (f), _end = (t); i >= _end; --i)
#define clr(c,x) memset(c,x,sizeof(c));
#define debug(x) cout<<"debug  "<<x<<endl;
const int INF = 0x3f3f3f3f;
typedef long long int64;

inline int RD(){ int res; scanf("%d",&res); return res; }

#define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas)

//*******************************************************************************

const int maxn = 10005;
struct Trie{
    int next[maxn*50][26];
    int fail[maxn*50];
    int end[maxn*50];
    int sz;
    void init(){ sz = 0; clr(next[0],0); }
    int newnode(){
        ++sz;
        clr(next[sz],0);
        fail[sz] = end[sz] = 0;
        return sz;
    }

    void insert(char *s){
        int u = 0;
        while(*s){
            int nid = *s++ - 'a';
            if(!next[u][nid]){
                next[u][nid] = newnode();
            }
            u = next[u][nid];
        }
        ++end[u];
    }

    void build(){
        queue<int> Q;
        int u = 0;
        rep(c,0,25){
            if(next[0][c]){
                Q.push(next[0][c]);
            }
        }
        while(!Q.empty()){
            u = Q.front();
            Q.pop();
            int fu = fail[u];
            rep(c,0,25){
                int v = next[u][c];
                if(v){
                    Q.push(v);
                    fail[v] = next[fu][c];
                }else{
                    next[u][c] = next[fu][c];
                }
            }
        }
    }

    int query(char *s){
        int u = 0;
        int ans = 0;
        while(*s){
            int nid = *s++ - 'a';
            u = next[u][nid];
            int k = u;
            while(k){
                if(end[k]){
                    ans += end[k];
                    end[k] = 0;
                }
                k = fail[k];
            }
        }
        return ans;
    }
}ac;
char str[1000009];
int main(){
    Rush{
        ac.init();
        int n;
        scanf("%d",&n);
        while(n--){
            scanf("%s",str);
            ac.insert(str);
        }
        ac.build();
        scanf("%s",str);
        printf("%d\n",ac.query(str));
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-05-06 20:38  DSChan  阅读(104)  评论(0编辑  收藏  举报