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

题目描述

有N个由小写字母组成的模式串以及一个文本串T。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串T中出现的次数最多。

输入格式

输入含多组数据。

每组数据的第一行为一个正整数N,表示共有N个模式串,1≤N≤150。

接下去NN行,每行一个长度小于等于70的模式串。下一行是一个长度小于等于10^6 的文本串T。

输入结束标志为N = 0

输出格式

样例

输入数据 1

2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0

输出数据 1

4
aba
2
alpha
haha

 

 

非常明显,这是一道AC自动机的题经典废话

懒得解释接下来的了,待会发个算法学习得了

复制代码
#include<bits/stdc++.h> 
using namespace std;
struct answer{
    int num,pos;
    bool operator<(const answer &a){
        if(num!=a.num) return num>a.num;
        else return pos<a.pos;
    }
}ans[1000010];
int n,cnt,ch[1000010][30],f[1000010],val[1000010];
string s[1000],s1;
void build(int num){
    int len = s[num].length(),now = 0;
    for(int i = 0;i<len;i++){
        if(ch[now][s[num][i]-'a']==0)
            ch[now][s[num][i]-'a'] = ++cnt;
        now = ch[now][s[num][i]-'a'];
    }
    val[now] = num;
}
void getfail(){
    queue<int>q;
    for(int i = 0;i<26;++i){
        if(ch[0][i]!=0){
            f[ch[0][i]] = 0;
            q.push(ch[0][i]);
        }
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i = 0;i<26;++i){
            if(ch[u][i]!=0){
                f[ch[u][i]] = ch[f[u]][i];
                q.push(ch[u][i]);
            }else ch[u][i] = ch[f[u]][i];
        }
    }
}
void acquery(){
    int l = s1.length(),now = 0;
    for(int i = 0;i<l;i++){
        now = ch[now][s1[i]-'a'];
        for(int t = now;t;t = f[t])
            ans[val[t]].num++;
    }
}
int main(){
    scanf("%d",&n);
    while(n){
        memset(f,0,sizeof(f));
        memset(val,0,sizeof(val));
        memset(ch,0,sizeof(ch));
        for(int i = 1;i<=n;i++){
            cin>>s[i];
            ans[i].num = 0;
            ans[i].pos = i;
            build(i);
        }
        cin>>s1;
        f[0] = 0;
        getfail();
        acquery();
        sort(ans+1,ans+n+1);
        printf("%d\n",ans[1].num);
        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;
        }
        scanf("%d",&n);
    }
    return 0;
}
复制代码

 

posted @   cztq  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示