hdu 3065 病毒侵袭持续中

来源:互联网 发布:移动硬盘装ubuntu 编辑:程序博客网 时间:2024/04/19 03:14

继续AC自动机水题。

这个题与上个题区别在于,需要统计出现次数,所以不能统计下就标记然后下次就不统计了,就比如样例AAA,出现AA是两次的。

再者就是,匹配串还有其他字符,需要判断一下,遇到其他字符的时候,直接指针移动到root。刚开始开了130个指针,果断MLE了。。

#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define BUG puts("here!!!")#define STOP system("pause")using namespace std;const int MAX_N = 26;struct NODE{int id;NODE *next[MAX_N], *fail;NODE(){id = -1;fail = NULL;memset(next, 0, sizeof(next));}}*head;void Build_trie(char *s,NODE *head,int id){int len = strlen(s);for(int i=0; i<len; i++){int k = s[i] - 'A';if( head->next[k] == NULL )head->next[k] = new NODE();head = head->next[k];}head->id = id;}queue<NODE*> q;void Build_fail(NODE *head){head->fail = NULL;q.push(head);while( !q.empty() ){NODE *now = q.front(); q.pop();for(int i=0; i<MAX_N; i++)if( now->next[i] ){NODE *p = now->fail;while( p ){if( p->next[i] ){now->next[i]->fail = p->next[i];break;}p = p->fail;}if( p == NULL )now->next[i]->fail = head;q.push(now->next[i]);}}}int cnt[1010];void AC_find(NODE *head, char *s){int len = strlen(s), sum = 0;NODE* p = head;for(int i=0; i<len; i++){if( !isupper(s[i]) ){p = head;continue;}int k = s[i] - 'A';while( p->next[k] == NULL && p != head )p = p->fail;p = p->next[k] == NULL ? head : p->next[k];NODE *tmp = p;while( tmp != head ){if( tmp->id != -1 )cnt[tmp->id]++;tmp = tmp->fail;}}}char s[2000005];char ss[1010][55];int main(){int n;while( ~scanf("%d", &n) ){head = new NODE();for(int i=0; i<n; i++){scanf("%s", ss[i]);Build_trie(ss[i], head, i);}Build_fail( head );scanf("%s", s);memset(cnt, 0, sizeof(cnt));AC_find( head, s);for(int i=0; i<n; i++)if( cnt[i] )printf("%s: %d\n",ss[i], cnt[i]);}return 0;}