zoukankan      html  css  js  c++  java
  • AC自动机模板

    引用自  kuangbin大神的博客  http://www.cnblogs.com/kuangbin/p/3164106.html

    写了一点自己理解的注释 方便自己查看

    HDU(2222)

    //======================
    // HDU 2222
    // 求目标串中出现了几个模式串
    //====================
    #include <stdio.h>
    #include <algorithm>
    #include <iostream>
    #include <string.h>
    #include <queue>
    using namespace std;
    
    struct Trie
    {
        int Next[500010][26];//26是这里讨论26个小写字母的情况,根据情况修改
        int fail[500010],end[500010];//end数组表示以该节点结尾的字符串的数量
        int root,L;//L用来标记节点序号,以广度优先展开的字典树的序号
        int newnode()  //建立新节点
        {
            for(int i = 0;i < 26;i++)
                Next[L][i] = -1;     //将该节点的后继节点域初始化
            end[L++] = 0;
            return L-1;    //返回当前节点编号
        }
        void init() //初始化操作
        {
            L = 0;
            root = newnode();
        }
        void insert(char buf[])
        {
            int len = strlen(buf);
            int now = root;
            for(int i = 0;i < len;i++)
            {
                if(Next[now][buf[i]-'a'] == -1)  //如果未建立当前的后继节点,建立新的节点
                    Next[now][buf[i]-'a'] = newnode();
                now = Next[now][buf[i]-'a'];
            }
            end[now]++;//以该节点结尾的字符串数量增加1
        }
        void build()
        {
            queue<int>Q; //用广度优先的方式,将树层层展开
            fail[root] = root;
            for(int i = 0;i < 26;i++)
                if(Next[root][i] == -1)
                    Next[root][i] = root;
                else
                {
                    fail[Next[root][i]] = root;
                    Q.push(Next[root][i]);
                }
            while( !Q.empty() )
            {
                int now = Q.front();
                Q.pop();
                for(int i = 0;i < 26;i++)
                    if(Next[now][i] == -1)
                        Next[now][i] = Next[fail[now]][i];//该段的最后一个节点匹配后,跳到拥有最大公共后缀的fail节点继续匹配
                    else
                    {
                        fail[Next[now][i]]=Next[fail[now]][i];//当前节点的fail节点等于它前驱节点的fail节点的后继节点
                        Q.push(Next[now][i]);
                    }
            }
        }
        int query(char buf[])
        {
            int len = strlen(buf);
            int now = root;
            int res = 0;
            for(int i = 0;i < len;i++)
            {
                now = Next[now][buf[i]-'a'];
                int temp = now;
                while( temp != root )
                {
                    res += end[temp];//加上以当前节点结尾的字符串数
                    end[temp] = 0;//该题是防止计算重复的字符串
                    temp = fail[temp];//每次找最大公共后缀对应的fail节点
                }
            }
            return res;
        }
        void debug()
        {
            for(int i = 0;i < L;i++)
            {
                printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
                for(int j = 0;j < 26;j++)
                    printf("%2d",Next[i][j]);
                printf("]
    ");
            }
        }
    };
    char buf[1000010];
    Trie ac;
    int main()
    {
        int  t,n,ans;
        scanf("%d",&t);
        while(t--)
        {
            ac.init();
           scanf("%d",&n);
           for(int i=0;i<n;i++)
           {
               scanf("%s",buf);
               ac.insert(buf);
           }
           ac.build();
             scanf("%s",buf);
             printf("%d
    ",ac.query(buf));
        }
        return 0;
    }
  • 相关阅读:
    原生js螺旋运动
    拉美电子游戏市场创收45亿美元
    ZOJ 3229 Shoot the Bullet
    Java的压缩、解压及压缩加密、解密解压 样例
    java环境变量配置
    git在myelispse中的安装
    java注解
    Python测试框架doctest
    python中的协程
    Flask log配置,实现按照日期自动生成日志文件
  • 原文地址:https://www.cnblogs.com/a249189046/p/7545939.html
Copyright © 2011-2022 走看看