(AC自动机)模板

来源:互联网 发布:洗衣机选购 知乎 编辑:程序博客网 时间:2024/05/22 02:11
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <queue>using namespace std;const int allSon=26;char patten[60];      ///模式串char text[1000010];   ///文本串int ans;struct TrieNode{    struct TrieNode *son[allSon];    struct TrieNode *fail;//失败指针    int num;//是不是一个单词}*root;TrieNode* createNode()//创建Tiree树并且完成对树的初始化{    TrieNode *p;    p = (TrieNode*)malloc(sizeof(TrieNode));    memset(p->son,0,sizeof(p->son));    p->num = 0;    p->fail = NULL;    return p;}///插入模式串,构建字典树void insertPatten(){    TrieNode *p;    p = root;    int index = 0;    while(patten[index])    {        int lowercase = patten[index]-'a';        if(p->son[lowercase]==NULL)        {            p->son[lowercase] = createNode();        }        p = p->son[lowercase];        index++;    }    p->num++;//到了单词的末尾 此时是一个单词则num置一}///求fail指针。构造AC自动机。void build_AC_automaton()//利用bfs构建失败指针 构建失败指针时需要注意对第二层进行处理 就是让第二层全部都指向根节点 让根节点的失败指针置为ULL{    TrieNode *p;    p = root;    queue<TrieNode*>qu;    qu.push(p);    while(!qu.empty())    {        p = qu.front();        qu.pop();        for(int i = 0; i < allSon; i++)        {            if(p->son[i] != NULL)  ///第i个孩子存在            {                if(p == root)  ///p是根,根节点的孩子的失败指针都指向自己                {                    p->son[i]->fail = root;                }                else                {                    TrieNode *node = p->fail;//如果node不为空 并且在node的儿子里也有字母z让这个失败指针指向失败指针的儿子                    while(node != NULL)                    {                        if(node->son[i]!=NULL)                        {                            p->son[i]->fail = node->son[i];                            break;                        }                        node = node->fail;                    }                    if(node == NULL)//如果到最后都没有找到node里面有字母z则直接让这个失败指针指向其root                        p->son[i]->fail = root;                }                qu.push(p->son[i]);//并将其插入队列里面            }        }    }}void find_in_AC_automaton(){    TrieNode *p;    p = root;    int index = 0;    while(text[index] != '\0')    {        int lowercase = text[index]-'a';        while(p->son[lowercase]==NULL && p!=root)            p = p->fail;        p = p->son[lowercase];        if(p == NULL) p = root;        TrieNode *temp = p;        while(temp!=NULL && temp->num!=-1)        {            ans += temp->num;            temp->num = -1;            temp = temp->fail;        }        index++;    }}void freeNode(TrieNode *node){    if(node != NULL)    {        for(int i = 0; i < allSon; i++)            freeNode(node->son[i]);    }    free(node);}int main(){    int t,n;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        root = createNode();        for(int i = 0; i < n; i++)        {            scanf("%s",patten);            insertPatten();        }        scanf("%s",text);        build_AC_automaton();        ans = 0;        find_in_AC_automaton();        printf("%d\n",ans);        freeNode(root);    }    return 0;}
原创粉丝点击