zoukankan      html  css  js  c++  java
  • hdu2222--Keywords Search+AC自己主动机模板

    题目链接:点击进入
    KMP对模式串进行处理。然后就能够方便的推断模式串是否在目标串中出现了;这显示适合一个模式串多个目标串的情况。可是假设模式串有多个,这时假设还用KMP则须要对每一个串都进行一次处理,显然不是非常合适。事实上这时候能够将全部模式串建成一棵trie树。然后採用相似于kmp的方法计算出failed指针,也就能够方便的进行匹配了。事实上这就是ac自己主动机的思想。

    代码例如以下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    const int maxn=500000+100;
    
    struct Trie
    {
        ///next数组表示的就是trie树
        ///fail数组记录了每一个节点的失败指针
        ///end数组记录了以当前节点作为结尾的字符串的个数
        int next[maxn][26],fail[maxn],end[maxn];
        ///root表示trie的根节点。L表示当前trie的节点总数
        int root,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]++;
        }
    
       ///採用bfs形式构造fail指针
        void build()
        {
            queue<int>Q;
            fail[root]=root;
            for(int i=0;i<26;i++)
            {
                ///假设当前节点的第i个儿子不存在
                ///则将其补上,为当前节点失败节点的第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];
                    else
                    {
                        fail[next[now][i]]=next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
            }
        }
    
        int query(char buf[])
        {
            int len=strlen(buf);
            int res=0;
            int now=root;
            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];
                }
            }
            return res;
        }
    };
    
    char str[maxn*2];
    Trie ac;
    
    int main()
    {
       int T;
       int n;
       scanf("%d",&T);
       while(T--)
       {
           scanf("%d",&n);
           ac.init();
           for(int i=0;i<n;i++)
           {
               scanf("%s",str);
               ac.insert(str);
           }
           ac.build();
           scanf("%s",str);
           printf("%d
    ",ac.query(str));
       }
      return 0;
    }
    
  • 相关阅读:
    with一个对象,自动触发__enter__方法
    SQLAlchemy-Utils
    SQLAlchemy
    wtforms
    Python数据库连接池DBUtils(基于pymysql模块连接数据库)
    VMWare安装linux centos,安装中文输入法
    HttpServletRequest和ServletRequest的区别
    Java序列化
    mybatis循环取序列,值相同问题处理
    利用jdk将wsdl生成java代码
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7169620.html
Copyright © 2011-2022 走看看