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

就是一道普通的ac自动机,温习一下,一定要注意数组的开的大小,楼主因为粗心,拌在这里了。
#include<bits/stdc++.h>
using namespace std;
const int MX=1e5+9;
int n,t[MX<<2][26],tot=1,fail[MX<<2],pos[MX<<2],num[MX],last[MX<<2];
char ss[1000009],s[200][MX];

void add(int id){
    int now=1;
    for( int i=0 ; s[id][i] ; i++ ){
        int a=s[id][i]-'a';
        if( !t[now][a] )
            t[now][a]=++tot;    // tot一定要和now相等
        now=t[now][a];
    }
    pos[now]=id;
}

void build(){
    queue<int> que;
    for( int i=0 ; i<=25 ; i++ ){
        if( t[1][i]!=0 ){
            que.push(t[1][i]);
            fail[t[1][i]]=1;
        }
        else
            t[1][i]=1;
    }
    while( !que.empty() ){
        int now=que.front();
        que.pop();
        for( int i=0 ; i<=25 ; i++ ){
            if( t[now][i] ){
                fail[t[now][i]]=t[fail[now]][i];
                que.push(t[now][i]);
            }
            else
                t[now][i]=t[fail[now]][i];
            last[t[now][i]]=(pos[fail[t[now][i]]]?fail[t[now][i]]:last[fail[t[now][i]]]);   // last数组可以加快搜索,在有一些情况下是必要的
        }
    }
    return ;
}

void Num(int now){
    while( now>0 ){
        num[pos[now]]++;
        now=last[now];
    }
    return ;
}

void ac(){
    int now=1;
    for( int i=0 ; ss[i] ; i++ ){
        int a=ss[i]-'a';
        if( t[now][a] )
            now=t[now][a];
        else
            now=fail[t[now][a]];
        Num(now);
    }
    int an=0;
    for( int i=1 ; i<=n ; i++ )
        if( an<=num[i] )
            an=num[i];
    printf("%d\n",an);
    for( int i=1 ; i<=n ; i++ )
        if( num[i]==an )
            printf("%s\n",s[i]);
}

int main()
{
  //  freopen("input.txt","r",stdin);
    while( scanf("%d",&n) && n ){
        memset(num,0,sizeof(num));
        memset(last,0,sizeof(last));
        memset(t,0,sizeof(t));
        memset(fail,0,sizeof(fail));
        for( int i=1 ; i<=n ; i++ ){
            scanf("%s",s[i]);
            add(i);
        }
        build();
        scanf("%s",ss);
        ac();
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值