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

    P3796 【模板】AC自动机(加强版)

    此题是在简单版的AC自动机基础上完成,直接附上代码

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    string t[maxn],s[maxn];
    struct tree
    {
        int fail;//失配指针
        int son[26];//一个节点最多有26个子节点
        int num;//标记以此节点为结尾
    }DFA[maxn]; //字典树
    int cnt=0;
    struct Result
    {
        int times;
        int pos;
    }ANS[maxn]; //记录单词出现次数
    bool cmp(Result a,Result b)
    {
        if(a.times!=b.times)
            return a.times>b.times;
        else
            return a.pos<b.pos;
    }
    void clean(int x)
    {
        memset(DFA[x].son,0,sizeof(DFA[x].son));
        DFA[x].fail=0;
        DFA[x].num=0;
    
    }
    void build(string s,int num)
    {
        int l=s.length();
        int now=0;//字典树当前指针
        for(int i=0;i<l;++i)
        {
            if(DFA[now].son[s[i]-'a']==0) //树上没有这个子节点
            {
                 DFA[now].son[s[i]-'a']=++cnt; //新增一个节点
                 clean(cnt);
            }
            now=DFA[now].son[s[i]-'a']; //向下构造
        }
        DFA[now].num=num;// 标记单词的结尾
    }
    void Get_fail() //构造fail指针
    {
        queue<int> Q;
        for(int i=0;i<26;++i)
        {
            if(DFA[0].son[i]!=0)
            {
                DFA[DFA[0].son[i]].fail=0;//指向根节点,第二层
                Q.push(DFA[0].son[i]); //压入队列
            }
        }
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            for(int i=0;i<26;++i)  //后面的层
            {
                if(DFA[u].son[i]!=0)//如果存在此节点
                {
                    DFA[DFA[u].son[i]].fail=DFA[DFA[u].fail].son[i];//指向该节点的父节点的fail值对应的节点的相同子节点
                    Q.push(DFA[u].son[i]); //加入队列
                }
                else //如果不存在这个节点
                {
                    DFA[u].son[i]=DFA[DFA[u].fail].son[i];  //当前节点的孩子节点指向当前节点的fail的孩子节点
                }
            }
        }
    }
    void query(string s)
    {
        int len=s.size();
        int now=0;
        for(int i=0;i<len;++i)
        {
            now=DFA[now].son[s[i]-'a'];//向下一层
            for(int t=now;t;t=DFA[t].fail) //循环求解
                ANS[DFA[t].num].times++;
            }
    }
    
    
    int main()
    {
        int n;
        while(1)
        {
            scanf("%d",&n);
            if(n==0)
                break;
            cnt=0;
            clean(0);
            for(int i=1;i<=n;++i)
            {
                cin>>s[i];
                ANS[i].times=0;
                ANS[i].pos=i;
                build(s[i],i);
            }
            DFA[0].fail=0; //结束标志
            Get_fail();//求出失配指针
            cin>>s[0]; //文本串
            query(s[0]);
            sort(ANS+1,ANS+n+1,cmp);
            printf("%d
    ",ANS[1].times);
            cout << s[ANS[1].pos] << endl;
            for(int i=2;i<=n;++i)
            {
                if(ANS[i].times==ANS[i-1].times)
                    cout<<s[ANS[i].pos]<<endl;
                else
                    break;
            }
        }
        return 0;
    }
  • 相关阅读:
    20000字干货笔记,一天搞定Mysql~【转】
    Linux操作系统概述及内核介绍
    如何在装有高版本NBU的主机上安装低版本的NBU?卸载8.0安装7.5记录
    vmware+kvm+vnc安装配置
    NBU异机恢复Oracle数据库,作业报错2850处理
    NetBackup 进程整理
    1、虚拟化实施流程、宿主机如何选型、如何进行性能测试
    灾难恢复的衡量指标RTO和RPO
    国内主要灾备厂商
    单例设计模式
  • 原文地址:https://www.cnblogs.com/acmer-hmin/p/11768232.html
Copyright © 2011-2022 走看看