码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-10-30 22:59:17      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:names   基础上   ==   sizeof   fail   end   div   str   tps   

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\n",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;
}

 

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

标签:names   基础上   ==   sizeof   fail   end   div   str   tps   

原文地址:https://www.cnblogs.com/acmer-hmin/p/11768232.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!