HDOJ 2222 Keywords Search

Accepted 2222 593MS 30816K 2430 B G++

第一道 AC 自动机,理解了就好写;

需要注意字典可能重复,重复的不能按一次算。

# include <cstdio>

# include <cstring>

# include <queue>



using namespace std;



# define WORD_LEN 50 + 5

# define MAXN 10000 + 5

# define ALPHA_SIZE 26



int n, id;

char t[1000000 + 10];

char w[MAXN][WORD_LEN];



struct node

{

    node * fail;

    node * next[ALPHA_SIZE];

    int id;

    int isEnd;        // 字典里有重复的单词 

    node ()

    {

        fail = NULL;

        memset(next, 0, sizeof(next));

        id = 0;

        isEnd = 0;

    }

}* root;





int alpha_map(char ch)

{

    return ch - 'a';

}



void insert_trie(node * root, char *s)

{

    int c, i;

    node * p = root;

    for (i = 0; s[i]; ++i)

    {

        c = alpha_map(s[i]);

        if (NULL == p->next[c]) p->next[c] = new node;

        p = p->next[c];

    }

    ++(p->isEnd);

}



void build_trie(node * root)

{

    for (int i = 0; i < n; ++i)

        insert_trie(root, w[i]);

}



void build_AC_auto(node *root)

{

    int i;

    node *cur, *tmp;

    queue <node *> Q;



    // 根节点的子节点单独处理

    Q.push(root);

    for (i = 0; i < ALPHA_SIZE; ++i)

    {

        if (root->next[i])

        {

            root->next[i]->fail = root;

            Q.push(root->next[i]);

        }

    }Q.pop();    // 根节点出队



    // 更新非根节点子节点的 fail

    while (!Q.empty())

    {

        cur = Q.front(); Q.pop();    // 当前节点出队

        for (i = 0; i < ALPHA_SIZE; ++i)

        {

            if (cur->next[i])

            {

                tmp = cur->fail;            // 找到当前节点的 fail

                // 更新子节点的 fail

                while (tmp)

                {

                    if (tmp->next[i])

                    {

                        cur->next[i]->fail = tmp->next[i];

                        break;

                    }

                    tmp = tmp->fail;

                }

                // 没有找到可以匹配的

                if (NULL == tmp)

                {

                    cur->next[i]->fail = root;

                }

                // 将子节点入队

                Q.push(cur->next[i]);

            }

        }

    }

}



int search(char *t, node * root)

{

    int i, c, ret = 0;

    node *tmp, *p = root;



    for (i = 0; t[i]; ++i)

    {

        c = alpha_map(t[i]);

        while (root != p && NULL == p->next[c]) p = p->fail;

        p = p->next[c];

        if (NULL == p) p = root;

        tmp = p;

        while (tmp)

        {

            if (tmp->isEnd)

            {

                ret += tmp->isEnd;

                tmp->isEnd = 0;

            }

            tmp = tmp->fail;

        }

    }



    return ret;

}



void init(void)

{

    id = 0;

    scanf("%d", &n);

    for (int i = 0; i < n; ++i)

        scanf("%s", w[i]);

    scanf("%s", t);

}



void solve(void)

{

    root = new node;

    build_trie(root);

    build_AC_auto(root);

    printf("%d\n", search(t, root));

}



int main()

{

    int T;



    scanf("%d", &T);

    while (T--)

    {

        init();

        solve();

    }



    return 0;

}

/**/

你可能感兴趣的:(search)