• AC自动机模板


    每个节点只访问一次。

    //子树节点是在插入时new的,
    //寻找失配指针中使用的队列是直接调用STL的
    const int kind = 26;
    struct node
    {
        node *fail;
        node *next[kind];
        int count;//记录当前前缀是完整单词出现的个数
        node()
        {
            fail = NULL;
            count = 0;
            memset(next,NULL,sizeof(next));
        }
    };
    
    void insert(char *str,node *root)
    {
        node *p=root;
        int i=0,index;
        while(str[i])
        {
            index = str[i]-'a';
            if(p->next[index]==NULL)
                p->next[index]=new node();
            p=p->next[index];
            i++;
        }
        p->count++;
    
    }
    
    
    //寻找失败指针
    void build_ac_automation(node *root)
    {
        int i;
        queue<node *>Q;
        root->fail = NULL;
        Q.push(root);
        while(!Q.empty())
        {
            node *temp = Q.front();//q[head++];//取队首元素
            Q.pop();
            node *p = NULL;
            for(i=0; i<kind; i++)
            {
                if(temp->next[i]!=NULL)//寻找当前子树的失败指针
                {
                    p = temp->fail;
                    while(p!=NULL)
                    {
                        if(p->next[i]!=NULL)//找到失败指针
                        {
                            temp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
    
                    if(p==NULL)//无法获取,当前子树的失败指针为根
                        temp->next[i]->fail = root;
    
                    Q.push(temp->next[i]);
                }
            }
        }
    }
    
    
    //询问str中包含n个关键字中多少种即匹配
    int query(node *root)
    {
        int i = 0,cnt = 0,index,len;
        len = strlen(str);
        node *p = root;
        while(str[i])
        {
            index = str[i]-'a';
            while(p->next[index]==NULL&&p!=root)//失配
                p=p->fail;
            p=p->next[index];
            if(p==NULL)//失配指针为根
                p = root;
    
            node *temp = p;
            while(temp!=root&&temp->count!=-1)//寻找到当前位置为止是否出现病毒关键字
            {
                //if(temp->count!=0)
                cnt+=temp->count;
                temp->count=-1;
                temp=temp->fail;
            }
            i++;
        }
        return cnt;
    }
    

    无限次访问的模板


    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    
    using namespace std;
    
    const int kind = 256;
    
    struct node
    {
        node *fail;
        node *next[kind];
        int count;
        bool visit;
        node()
        {
            fail = NULL;
            count = 0;
            visit = false;
            memset(next,NULL,sizeof(next));
        }
    };
    node* query_temp_que[1111];
    void insert(unsigned char *str,node *root,int slen)
    {
        node *p=root;
        int i,index;
        for (i=0;i<slen;i++)
        {
            index = (int)str[i];
            if(p->next[index]==NULL) p->next[index]=new node();
            p=p->next[index];
        }
        p->count++;
    }
    
    //寻找失败指针
    void build_ac_automation(node *root)
    {
        int i;
        queue<node *>Q;
        root->fail = NULL;
        Q.push(root);
        while(!Q.empty())
        {
            node *temp=Q.front();//q[head++];//取队首元素
            Q.pop();
            node *p=NULL;
            for(i=0; i<kind; i++)
            {
                if(temp->next[i]!=NULL)//寻找当前子树的失败指针
                {
                    p=temp->fail;
                    while(p!=NULL)
                    {
                        if(p->next[i]!=NULL)//找到失败指针
                        {
                            temp->next[i]->fail=p->next[i];
                            break;
                        }
                        p=p->fail;
                    }
                    if(p==NULL)//无法获取,当前子树的失败指针为根
                        temp->next[i]->fail=root;
                    Q.push(temp->next[i]);
                }
            }
        }
    }
    
    //询问str中包含n个关键字中多少种即匹配
    int query(unsigned char *str,node *root,int slen)
    {
        int i,cnt = 0,index;
        int head,tail;
        head=tail=0;
        node *p = root;
        for (i=0;i<slen;i++)
        {
            index = (int)str[i];
            while(p->next[index]==NULL&&p!=root) p=p->fail;
            p=p->next[index];
            if(p==NULL) p = root;
            node *temp = p;
            while(temp!=root&&!temp->visit)//寻找到当前位置为止是否出现病毒关键字
            {
                cnt+=temp->count;
                temp->visit=true;
                query_temp_que[tail++]=temp;
                temp=temp->fail;
            }
        }
        while (head<tail)
        {
            node* cur=query_temp_que[head++];
            cur->visit=false;
        }
        return cnt;
    }







  • 相关阅读:
    素数推断算法(高效率)
    Hibernate的fetch
    TRIZ系列-创新原理-22-变害为利原理
    Offer是否具有法律效力?
    浅谈C++多态性
    C语言scanf函数详解
    大话设计模式之原型模式
    Android源码文件夹结构
    简单的REST的框架实现
    android startActivityForResult的用法
  • 原文地址:https://www.cnblogs.com/cyendra/p/3038380.html
Copyright © 2020-2023  润新知