HDU 3065 - 病毒侵袭持续中 (AC自动机)

来源:互联网 发布:临沂淘宝客服招聘 编辑:程序博客网 时间:2024/06/06 09:03

病毒侵袭持续中

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


Problem Description
小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
 

Input
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
 

Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
 

Sample Input
3AABBCCooxxCC%dAAAoen....END
 

Sample Output
AA: 2CC: 1
Hint
Hit:题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。计数策略也可一定程度上从Sample中推测。
 

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

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


AC自动机模板题


#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 = 500000 + 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 add(int j) {        if(j) {            val[j]++;            add(last[j]);        }    }    void query(char * T) {        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]) add(j);            else if(last[j]) add(last[j]);        }    }    int cnt(char * s) {        int u = 0;        int n = strlen(s);        for(int i=0; i<n; i++) {            int c = idx(s[i]);            u = ch[u][c];        }        return val[u] - 1;    }};ACAutomata ac;char dic[1020][60];char s[2000000 + 20];int main() {    int n;    while(scanf("%d", &n) != EOF) {        ac.init();        for(int i=0; i<n; i++) {            scanf("%s", dic[i]);            ac.insert(dic[i], 1);        }        ac.build();        scanf("%s", s);        ac.query(s);        for(int i=0; i<n; i++) {            int cnt = ac.cnt(dic[i]);            if(cnt > 0) printf("%s: %d\n", dic[i], cnt);        }    }    return 0;}




0 0
原创粉丝点击