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

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define endl '\n'
const double pi = acos(-1);
const int maxn = 155;
const int maxm = 75;
const int N = 1e6 + 10;
const ll mod = 1e9+7;
int n;
char s[maxn][maxm], ss[N];
struct nod{
    int num, pos;
}ans[N];
bool operator< (const nod& a, const nod& b){
        if(a.num == b.num) return a.pos < b.pos;
        else return a.num > b.num;
}
struct node{
    int tr[maxn*maxm][26], cnt;
    int e[maxn*maxm];
    int fail[maxn*maxm];
    void insert(char *s, int id){
        int p = 0;
        for(int i = 0 ; s[i] ; ++ i){
            int k = s[i] - 'a';
            if(!tr[p][k]) tr[p][k] = ++ cnt;
            p = tr[p][k];
        }
        e[p] = id;
    }
    void build(){
        queue<int> que;
        memset(fail, 0, sizeof(fail));
        for(int i = 0 ; i < 26 ; ++ i) if(tr[0][i]) que.push(tr[0][i]);
        while(!que.empty()){
            int k = que.front();
            que.pop();
            for(int i = 0 ; i < 26 ; ++ i){
                if(tr[k][i]){
                    fail[tr[k][i]] = tr[fail[k]][i];
                    que.push(tr[k][i]);
                }
                else tr[k][i] = tr[fail[k]][i];
            }
        }
    }
    int query(char *t){
        int p = 0, res = 0;
        for(int i = 0 ; t[i] ; ++ i){
            p = tr[p][t[i] - 'a'];
            for(int j = p ; j ; j = fail[j]){
                ans[e[j]].num ++;
            }
        }
        return res;
    }
};
node ac;
int main(){
    while(scanf("%d", &n) && n){
        memset(ac.tr, 0, sizeof(ac.tr));
        memset(ac.e, 0, sizeof(ac.e));
        ac.cnt = 0;
        for(int i = 1 ; i <= n ; ++ i){
            scanf("%s", s[i]);
            ac.insert(s[i], i);
            ans[i].pos = i;
            ans[i].num = 0;
        }
        ac.build();
        scanf("%s", ss);
        ac.query(ss);
        sort(ans + 1, ans + 1 + n);
        cout << ans[1].num << endl;
        cout << s[ans[1].pos] << endl;
        for(int i = 2 ; i <= n ; ++ i){
            if(ans[i].num == ans[1].num) cout << s[ans[i].pos] << endl;
            else break;
        }
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值