zoukankan      html  css  js  c++  java
  • 【模板】AC自动机(加强版)

    emm。。。AC自动机加强版?

    还是没啥变化。。。QVQ

    相较于简单版,模板没有丝毫改变

    只是这次要记录下那个子串是出现最多的就好了。。。QVQ

    为了方便,我们可以直接用 string 类型

    然鹅 string 类型的数组是不leng用 scanf 读的。。。QVQ

    所以代码跑的巨慢。。。

    呆码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    string s[100010];
    int cnt=0;
    
    struct asd{
        int fail;//失配指针
        int vis[26];//子节点的位置
        int end;//标记以这个节点结尾的单词编号 
    } AC[100010];//Trie树
    
    struct sdf{
        int num;
        int pos;
    } ans[100010];//所有单词的出现次数 
    
    inline void insert(string s,int num)
    {
            int l=s.length();
            int now=0; // 字典树的当前指针 
            for(int i=0;i<l;++i) // 构造Trie树
            {
                    if(AC[now].vis[s[i]-'a']==0) // Trie树没有这个子节点
                    {
                        AC[now].vis[s[i]-'a']=++cnt; // 构造出来
                    }
                    now=AC[now].vis[s[i]-'a']; // 向下构造 
            }
            AC[now].end=num; // 标记单词结尾 
    }
    
    inline void get_fail() // 构造fail指针
    {
            queue<int> Q; // 队列 
            for(int i=0;i<=25;++i) // 第二层的fail指针提前处理一下
                   if(AC[0].vis[i]!=0)
                       Q.push(AC[0].vis[i]);//压入队列 
    
            while(!Q.empty()) // BFS求fail指针 
            {
                  int u=Q.front();
                  Q.pop();
                  for(int i=0;i<=25;++i) // 枚举所有子节点
                  {
                            if(AC[u].vis[i]!=0) // 存在这个子节点
                          {
                                    AC[AC[u].vis[i]].fail=AC[AC[u].fail].vis[i];
                                    // 子节点的fail指针指向当前节点的
                                    // fail指针所指向的节点的相同子节点 
                                    Q.push(AC[u].vis[i]); // 压入队列 
                          }
                          else // 不存在这个子节点 
                          AC[u].vis[i]=AC[AC[u].fail].vis[i];
                          // 当前节点的这个子节点指向当
                          // 前节点fail指针的这个子节点 
                  }
            }
    }
    
    inline void query(string s) // AC自动机匹配
    {
            int l=s.length();
            int now=0;
            for(int i=0;i<l;++i)
            {
                    now=AC[now].vis[s[i]-'a']; // 向下一层
                    for(int j=now;j;j=AC[j].fail) // 循环求解
                        ans[AC[j].end].num++;
            }
    }
    
    inline bool cmp(sdf x,sdf y)
    {
        if(x.num==y.num) return x.pos<y.pos;
        else return x.num>y.num;
    }
    
    int main()
    {
        int n;
        while(1)
        {
            cin>>n; cnt=0;
            if(n==0) break;
            memset(AC,0,sizeof(AC));
            for(int i=1;i<=n;++i)
            {
                cin>>s[i];
                ans[i].num=0;
                ans[i].pos=i;
                insert(s[i],i);
            }
    
            get_fail();//求出失配指针
            cin>>s[0];
            query(s[0]);
            sort(ans+1,ans+1+n,cmp);
            printf("%d
    ",ans[1].num);
            cout<<s[ans[1].pos]<<endl;
            for(int i=2;i<=n;++i)
            {
                if(ans[i].num==ans[i-1].num)
                    cout<<s[ans[i].pos]<<endl;
                else break;
            }
        }
        return 0;
    }
    AC自动机(加强版)
  • 相关阅读:
    IO 模型
    进程、线程、锁
    用多线程,实现并发,TCP
    同步锁(互斥锁),GIL锁(解释器层面的锁),死锁与递归锁
    Java项目中的常用的异常2
    JAVA项目中的常用的异常处理情况1
    添加学生信息web界面连接数据库
    jdbc下载路径
    添加学生信息 web界面 并且连接数据库
    正则表达式
  • 原文地址:https://www.cnblogs.com/zzzyc/p/8867627.html
Copyright © 2011-2022 走看看