hdu 2222

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define N 1000010
#define WORD_SIZE 26
#define WORD_START 'a'
using namespace std;
class Node
{
public :
    int next[WORD_SIZE];
    int count;
    int fail;
};

class AC_automation
{

public :
    Node tree[N];
    int cur_id;
    int q[N];
    int root;
    AC_automation()
    {
        cur_id = 0;
        root = 0;
        init_node(root);
    }
    void insert_word( char *str );
    void init_node( int p );
    void build_AC( int p );
    void clear();
    int query_word( char *s, int p );
};

void AC_automation::clear()
{
    cur_id = 0;
    root = 0;
    init_node(root);
}
void AC_automation::init_node( int p )
{
    for( int i = 0; i < WORD_SIZE; i ++ )
    {
        tree[p].next[i] = -1;
    }
    tree[p].count = 0;
    tree[p].fail = -1;
}

void AC_automation::insert_word( char *str )
{
    int p = root, u;
    while( *str )
    {
        u = *str - WORD_START;
        if( tree[p].next[u] == -1 )
        {
            init_node(++cur_id);
            tree[p].next[u] = cur_id;
        }
        p = tree[p].next[u];
        str++;
    }
    tree[p].count++;
}

void AC_automation::build_AC( int p )
{
    int front = 0, rear = 0, t;
    tree[p].fail = root;
    q[ rear++] = p;
    while( front != rear )
    {
        p = q[ front ++];
        for( int i = 0; i < WORD_SIZE; i ++ )
        {
            if( tree[p].next[i] != -1 )
            {
                if( p == root ) tree[ tree[p].next[i] ].fail = root;
                else
                {
                    t = tree[p].fail;
                    while( t != root && tree[t].next[i] == -1 ) t = tree[t].fail;
                    if( tree[t].next[i] != -1 ) tree[ tree[p].next[i] ].fail = tree[t].next[i];
                    else tree[ tree[p].next[i] ].fail = root;
                }
                q[ rear ++ ] = tree[p].next[i];
            }
        }
    }
}

int AC_automation::query_word( char *s, int p )
{
    int u,q, ans = 0;
    while( *s )
    {
        u = *s - WORD_START;
        while( p != root && tree[p].next[u] == -1 ) p = tree[p].fail;
        p = tree[p].next[u];
        if( p == -1 ) p = root;
        q = p;;
        while( q!=root && tree[q].count != -1 )
        {
            ans += tree[q].count;
            tree[q].count = -1;
            q = tree[q].fail;
        }
        s++;
    }
    return ans;
}

char s[N];
AC_automation AC;
int main()
{
    int cas,n;
    char str[55];
    scanf("%d",&cas);
    while( cas -- )
    {
        AC.clear();
        scanf("%d",&n);
        while( n -- )
        {
            scanf("%s",str);
            AC.insert_word(str);
        }
        AC.build_AC(AC.root);
        scanf("%s",s);
        printf("%d\n",AC.query_word( s, AC.root) );
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值