HDU 2896 - 病毒侵袭 (AC自动机)

来源:互联网 发布:灵魂相认知乎 编辑:程序博客网 时间:2024/04/30 22:53

病毒侵袭

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10820    Accepted Submission(s): 2811


Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
 

Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
 

Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
 

Sample Input
3aaabbbccc2aaabbbcccbbaacc
 

Sample Output
web 1: 1 2 3total: 1
 

Source
2009 Multi-University Training Contest 10 - Host by NIT
 

Recommend
gaojie   |   We have carefully selected several similar problems for you:  3065 2243 2825 3341 3247



裸AC自动机,每个单词节点保存ID即可


#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cstring>#include <string>#include <map>#include <cmath>#include <queue>#include <set>using namespace std;//#define WIN#ifdef WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#define oform1 "%I64d"#elsetypedef long long LL;#define iform "%lld"#define oform "%lld\n"#define oform1 "%lld"#endif#define S64I(a) scanf(iform, &(a))#define P64I(a) printf(oform, (a))#define P64I1(a) printf(oform1, (a))#define REP(i, n) for(int (i)=0; (i)<n; (i)++)#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)const int INF = 0x3f3f3f3f;const double eps = 10e-9;const double PI = (4.0*atan(1.0));const int MAX_NODE = 100000 + 20;const int SIGMA_SIZE = 108;struct ACAutomata {    int ch[MAX_NODE][SIGMA_SIZE];    int val[MAX_NODE];    int f[MAX_NODE];    int last[MAX_NODE];    int sz;    void init() {        sz = 1; memset(ch[0], 0, sizeof(ch[0]));    }    int idx(char c) { return c - 20; }    void insert(char * s, int v) {        int n = strlen(s);        int u = 0;        for (int i=0; i<n; i++) {            int c = idx(s[i]);            if(!ch[u][c]) {                memset(ch[sz], 0, sizeof(ch[sz]));                val[sz] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        val[u] = v;    }    void build() {        queue<int> Q;        f[0] = 0;        for (int i=0; i<SIGMA_SIZE; i++) {            int u = ch[0][i];            if(u) { Q.push(u); f[u] = last[u] = 0; }        }        while (!Q.empty()) {            int r = Q.front(); Q.pop();            for (int c=0; c<SIGMA_SIZE; c++) {                int u = ch[r][c];                if(!u) continue;                Q.push(u);                int v = f[r];                while (v && !ch[v][c]) v = f[v];                f[u] = ch[v][c];                last[u] = val[f[u]] ? f[u] : last[f[u]];            }        }    }    void print(int j, set<int> & res) {        if(j) {            res.insert(val[j]);            print(last[j], res);        }    }    void query(char * T, set<int> & res) {        int n = strlen(T);        int j = 0;        for (int i=0; i<n; i++) {            int c = idx(T[i]);            while(j && !ch[j][c]) j = f[j];            j = ch[j][c];            if(val[j]) print(j, res);            else if(last[j]) print(last[j], res);        }    }};ACAutomata ac;char s[10000 + 20];int main() {    int n;    while(scanf("%d", &n) != EOF) {        ac.init();        for(int i=1; i<=n; i++) {            scanf("%s", s);            ac.insert(s, i);        }        ac.build();        int m;        scanf("%d", &m);        int tot = 0;        for(int i=1; i<=m; i++) {            scanf("%s", s);            set<int> res;            ac.query(s, res);            if(res.size() > 0) {                printf("web %d:", i);                for(set<int>::iterator it = res.begin(); it != res.end(); it++) {                    printf(" %d", *it);                }                putchar('\n');                tot++;            }        }        printf("total: %d\n", tot);    }    return 0;}







0 0
原创粉丝点击