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

it2025-01-06  19

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

Problem Description

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

Input

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

Output

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

Sample Input

3 AA BB CC ooxxCC%dAAAoen....END

Sample Output

AA: 2 CC: 1

Hit:

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

解题思路

AC自动机模板题,加深了对AC自动机的理解

代码1用指针实现trie树

#define _CRT_SECURE_NO_WARNINGS #include <cstdlib> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <string> #include <map> #define Mod 1000000 #define ll long long #define se second #define fi first #define pb push_back #define INF 0x3f3f3f3f #define de(x) cout << #x << " = "<< x << endl; #define eps 1e-6 #define lson l, mid, t<<1 #define rson mid+1, r, t<<1|1 #define rep(i,a,b) for (int i=(a);i<(b);++i) #define per(i,a,b) for (int i=(a);i>(b);--i) #define sz(a) (a).size() #define vi vector<int > using namespace std; int n, m, T; char s[1005][55]; int ans[1005]; char a[2000005]; struct node { node *next[30]; node *fail; int sum; node() { fail = NULL; rep(i, 0, 28) next[i] = NULL; sum = 0; } }*root; node *q[500005]; void insert(char *s, int t) { int m = strlen(s); node *p = root; rep(i, 0, m) { int x = s[i] - 'A'; if (p->next[x] == NULL) { node *newnode = new node(); p->next[x] = newnode; } p = p->next[x]; } p->sum = t; } void build_fail() { int head = 1, tail = 1; q[1] = root; while (head <= tail) { node *temp = q[head++]; rep(i, 0, 26) if (temp->next[i] != NULL) { if (temp == root) temp->next[i]->fail = root; else { node *p = temp->fail; while (p != NULL) { if (p->next[i] != NULL) { temp->next[i]->fail = p->next[i]; break; } p = p->fail; } if (p == NULL) temp->next[i]->fail = root; } q[++tail] = temp->next[i]; } } } void ac_automaton(char *s) { node *p = root; int m = strlen(s); rep(i, 0, m) { int x = s[i] - 'A'; if (s[i] < 'A' || s[i] > 'Z') { p = root; continue; } while (p->next[x] == NULL && p != root) p = p->fail; p = p->next[x]; if (p == NULL) p = root; node *temp = p; while (temp != root) { if (temp->sum > 0) ans[temp->sum]++; temp = temp->fail; } } } int main() { while (~scanf("%d", &n)) { memset(ans, 0, sizeof(ans)); root = new node(); for (int i = 1; i <= n; i++) { scanf("%s", s[i]); insert(s[i], i); } scanf("%s", a); build_fail(); ac_automaton(a); for (int i = 1; i <= n; i++) { if (ans[i]) printf("%s: %d\n", s[i], ans[i]); } } //system("pause"); return 0; }

代码2 zp学长的AC自动机模板%%% (ac_automaton部分是我自己添加的)

#define _CRT_SECURE_NO_WARNINGS #include <cstdlib> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <string> #include <map> #define Mod 1000000 #define ll long long #define se second #define fi first #define pb push_back #define INF 0x3f3f3f3f #define de(x) cout << #x << " = "<< x << endl; #define eps 1e-6 #define lson l, mid, t<<1 #define rson mid+1, r, t<<1|1 #define rep(i,a,b) for (int i=(a);i<(b);++i) #define per(i,a,b) for (int i=(a);i>(b);--i) #define sz(a) (a).size() #define vi vector<int > using namespace std; int n, m, T; char s[1005][55]; int ans[1005]; char a[2000005]; struct Trie{//[0,L),N−1isvirtual,0isrt,init!! static const int N = 101010,M = 26; int ne[N][M],fail[N],fa[N],rt,L,num[N]; void ini() { fill_n(ne[fail[0] = N-1],M,0); memset(num, 0, sizeof(num)); L = 0; rt = newnode(); } int newnode() { fill_n(ne[L],M,0); return L++; } void add(char*s, int t) { int p = rt; for (int i = 0; s[i]; ++i) { int c = s[i]-'A';//modify if(!ne[p][c])ne[p][c]=newnode(),fa[L-1]=p; p=ne[p][c]; } num[p] = t; } void Build() { vi v; v.pb(rt); rep(i,0,sz(v)) { int c=v[i]; rep(i,0,M)ne[c][i]? v.pb(ne[c][i]), fail[ne[c][i]]=ne[fail[c]][i]: ne[c][i]=ne[fail[c]][i]; } } void ac_automaton(char *a) { int rt = 0, m = strlen(a); rep(i, 0, m) { int x = a[i] - 'A'; if (a[i]<'A' || a[i]>'Z') { rt = 0; continue; } while (!ne[rt][x] && rt != 0) rt = fail[rt]; int temp = rt = ne[rt][x]; while (temp) { if (num[temp] > 0) ans[num[temp]]++; temp = fail[temp]; } } } }trie; int main() { while (~scanf("%d", &n)) { memset(ans, 0, sizeof(ans)); trie.ini(); for (int i = 1; i <= n; i++) { scanf("%s", s[i]); trie.add(s[i], i); } trie.Build(); scanf("%s", a); trie.ac_automaton(a); for (int i = 1; i <= n; i++) { if (ans[i]) printf("%s: %d\n", s[i], ans[i]); } } //system("pause"); return 0; }

转载于:https://www.cnblogs.com/seast90/p/9395011.html

相关资源:数据结构—成绩单生成器
最新回复(0)