【Trie树&AC自动机】P3879[TJOI2010]阅读理解 P3808 【模板】AC自动机(简单版)P3796 【模板】AC自动机(加强版)

洛谷 P3879[TJOI2010]阅读理解

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
typedef long long int LL;
const int INF = 0x7fffffff, SCF = 0x3fffffff;
const int N = 5e6+4, M = 1e3+4;
int n,m,k;
int idx,len,ans;
int has[M];
char ss[22];
struct TT
{
    int nxt[26],id;
}tree[N];
void jointree(int rt)
{
    len = strlen(ss);
    for(int i=0; i<len; i++){
        int pp = ss[i]-'a';
        if(!tree[rt].nxt[pp]){
            tree[rt].nxt[pp] = idx++;
        }
        rt = tree[rt].nxt[pp];
    }
    tree[rt].id = 1;
}
void qry(int rt)
{
    int root = rt;
    for(int i=0; i<len; i++){
        int pp = ss[i]-'a';
        if(!tree[rt].nxt[pp]) return ;
        rt = tree[rt].nxt[pp];
    }
    has[root] = tree[rt].id;
}
void solve()
{
    memset(has,0,sizeof(has));
    len = strlen(ss);
    for(int i=1; i<=n; i++){
        qry(i);
    }
    for(int i=1; i<=n; i++){
        if(has[i]) printf("%d ",i);
    }
    printf("\n");
}
int main()
{
    scanf("%d",&n);
    idx = n+1;
    for(int i=1; i<=n; i++){
        scanf("%d",&k);
        for(int j=1; j<=k; j++){
            scanf("%s",ss);
            jointree(i);
        }
    }
    scanf("%d",&m);
    for(int i=0; i<m; i++){
        scanf("%s",ss);
        solve();
    }
    return 0;
}

洛谷 P3808 【模板】AC自动机(简单版)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
typedef long long int LL;
const int INF = 0x7fffffff, SCF = 0x3fffffff;
const int N = 1e7+4, M = 1e3+4;
int n,idx;
char ss[N];
struct TT
{
    int fail,id,nxt[26];
}tree[N];
void joinTree()
{
    int len = strlen(ss), rt = 0;
    for(int i=0; i<len; i++){
        int pp = ss[i]-'a';
        if(!tree[rt].nxt[pp]){
            tree[rt].nxt[pp] = idx++;
        }
        rt = tree[rt].nxt[pp];
    }
    tree[rt].id += 1;
}
void getFail()
{
    std::queue<int> q;
    int x,y,fail;
    for(int i=0; i<26; i++){
        y = tree[0].nxt[i];
        if(y>0){
            tree[y].fail = 0;
            q.push(y);
        }
    }
    while(!q.empty()){
        x = q.front(); q.pop();
        fail = tree[x].fail;
        for(int i=0; i<26; i++){
            y = tree[x].nxt[i];
            if(y>0){
                tree[y].fail = tree[fail].nxt[i];
                q.push(y);
            }
            else tree[x].nxt[i] = tree[fail].nxt[i];
        }
    }
}
int ACgo()
{
    int rt = 0,len = strlen(ss),ans = 0;
    for(int i=0; i<len; i++){
        rt = tree[rt].nxt[ss[i]-'a'];
        for(int j=rt; j && tree[j].id != -1; j=tree[j].fail){
            ans += tree[j].id;
            tree[j].id = -1;
        }
    }
    return ans;
}
int main()
{
    //freopen("D:\\EdgeDownloadPlace\\P3808_2.in","r",stdin);
    idx = 1;
    scanf("%d",&n);
    while(n--){
        scanf("%s",ss);
        joinTree();
    }
    getFail();
    scanf("%s",ss);
    printf("%d",ACgo());
    return 0;
}

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

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
typedef long long int LL;
const int INF = 0x7fffffff, SCF = 0x3fffffff;
const int N = 1e6+4, M = 10550;
int n;
int idx;
struct TT
{
    int fail,id,nxt[26];
}node[M];
char ss[N];
char sub[155][75];
int save[155];
void initial()
{
    for(int i=0; i<=idx; i++){
        memset(node[i].nxt,0,sizeof(node[i].nxt));
        node[i].fail = 0;
        node[i].id = 0;
    }
    idx = 0;
    memset(save,0,sizeof(save));
}
void joinTree(int id)
{
    int len = strlen(sub[id]) ,rt = 0;
    for(int i=0; i<len; i++){
        int ch = sub[id][i]-'a';
        if(!node[rt].nxt[ch]) node[rt].nxt[ch] = ++idx;
        rt = node[rt].nxt[ch];
    }
    node[rt].id = id;
}
void buildFail()
{
    std::queue<int >q;
    for(int i=0; i<26; i++){
        if(node[0].nxt[i]>0) {
            node[node[0].nxt[i]].fail = 0;
            q.push(node[0].nxt[i]);
        }
    }
    while(!q.empty()){
        int cur = q.front(); q.pop();
        int fail = node[cur].fail;
        for(int i=0; i<26; i++){
            int next = node[cur].nxt[i];
            if(next>0){
                node[next].fail = node[fail].nxt[i];
                q.push(next);
            }
            else node[cur].nxt[i] = node[fail].nxt[i];
        }
    }
}
void ACgo()
{
    int len = strlen(ss),rt = 0;
    for(int i=0; i<len; i++){
        rt = node[rt].nxt[ss[i]-'a'];
        for(int j=rt; j; j=node[j].fail)
            save[node[j].id] += 1;
    }
}
int main()
{
    //freopen("D:\\EdgeDownloadPlace\\P3796_1.in","r",stdin);
    while(scanf("%d",&n)){
        if(n == 0) break;
        initial();
        for(int i=1; i<=n; i++){
            scanf("%s",sub[i]);
            joinTree(i);
        }
        buildFail();
        scanf("%s",ss);
        ACgo();
        int mx = 0;
        for(int i=1; i<=n; i++){
            mx = std::max(save[i],mx);
        }
        printf("%d\n",mx);
        for(int i=1; i<=n; i++){
            if(save[i] == mx){
                printf("%s\n",sub[i]);
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值