hdu2896 病毒侵袭

题面在这里

题意:

给n个模式串和m个文本串,问有几个文本串包含任意一个模式串,并且输出每个包含任意模式串的文本串,包含的是哪几个模式串。

做法:

ac自动机模板。
整天模板题做做还有什么希望(大雾)模板居然调了一个小时

代码:

/*************************************************************
    Problem: hdu 2896 病毒侵袭
    User: fengyuan07
    Language: C++
    Result: Accepted
    Time: 265MS
    Memory: 31364K
    Submit_Time: 2018-01-12 00:09:08
*************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<queue>
using namespace std;

const int N = 110000, M = 130;
int n, m, tot, all, cas, sum;
int c[N][M], w[N], fail[N], vis[N], ans[N];
char s[N];

inline void insert(char s[], int id)
{
    int len = strlen(s), o = 0;
    for(int i = 0; i < len; i ++) {
        if(!c[o][s[i]]) c[o][s[i]] = ++ tot;
        o = c[o][s[i]];
    }
    w[o] = id;
}
inline void build()
{
    queue<int> q;
    for(int i = 0; i <= 128; i ++) { if(c[0][i]) q.push(c[0][i]); fail[c[0][i]] = 0; }
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(int i = 0; i <= 128; i ++) if(c[u][i]) {
            fail[c[u][i]] = c[fail[u]][i];
            q.push(c[u][i]);
        } else c[u][i] = c[fail[u]][i];
    }
}
inline void query(char s[])
{
    int len = strlen(s), o = 0;
    for(int i = 0; i < len; i ++) {
        o = c[o][s[i]];
        for(int j = o; j && !vis[j]; j = fail[j]) {
            if(w[j]) ans[++ sum] = w[j];
            vis[j] = 1;
        }
    }
}
int main()
{
    scanf("%d", &n); getchar();
    for(int i = 1; i <= n; i ++) {
        gets(s);
        insert(s, i);
    }
    build();
    scanf("%d", &m); getchar();
    for(int i = 1; i <= m; i ++) {
        memset(vis, 0, sizeof vis); sum = 0;
        gets(s);
        query(s);
        if(sum > 0) {
            all ++;
            printf("web %d:", i); sort(ans+1, ans+1+sum);
            for(int j = 1; j <= sum; j ++) printf(" %d", ans[j]);
            puts("");
        }
    }
    printf("total: %d\n", all);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值