/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rights reserved. URL : http://acm.hdu.edu.cn/showproblem.php?pid=3065 Name : 3065 病毒侵袭持续中 Date : Sunday, August 21, 2011 Time Stage : one hour and a half Result: 4463980 2011-08-21 16:05:47 Accepted 3065 156MS 5900K 3738 B C++ pyy 4463875 2011-08-21 15:54:25 Wrong Answer 3065 187MS 5900K 3703 B C++ pyy 4463866 2011-08-21 15:53:38 Wrong Answer 3065 312MS 27400K 3716 B C++ pyy 4463803 2011-08-21 15:47:02 Runtime Error (ACCESS_VIOLATION) 3065 46MS 27328K 3716 B C++ pyy 4463790 2011-08-21 15:45:11 Runtime Error (ACCESS_VIOLATION) 3065 31MS 8264K 3680 B C++ pyy 4463772 2011-08-21 15:43:07 Runtime Error (ACCESS_VIOLATION) 3065 31MS 6288K 3670 B C++ pyy 4463765 2011-08-21 15:42:21 Runtime Error (ACCESS_VIOLATION) 3065 0MS 252K 3677 B C++ pyy 4463755 2011-08-21 15:41:44 Runtime Error (ACCESS_VIOLATION) 3065 31MS 5840K 3675 B C++ pyy 4463744 2011-08-21 15:41:03 Runtime Error (ACCESS_VIOLATION) 3065 31MS 5844K 3673 B C++ pyy 4463739 2011-08-21 15:40:09 Runtime Error (ACCESS_VIOLATION) 3065 31MS 5844K 3671 B C++ pyy 4463734 2011-08-21 15:39:38 Runtime Error (ACCESS_VIOLATION) 3065 31MS 5836K 3670 B C++ pyy 4463728 2011-08-21 15:39:01 Runtime Error (ACCESS_VIOLATION) 3065 31MS 5828K 3668 B C++ pyy Test Data: Review: 犯了很多低级的错误,也犯了一些严重的错误…… //----------------------------------------------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define SafeAccess(a, b) (0 <= (a) && (a) < n && 0 <= (b) && (b) < n) #define infinity 0x0f0f0f0f #define minus_inf 0x80808080 #define MAXSIZE 2000009 #define LESSMAX 55 #define CHARNUM 26 typedef struct tagNODE { int cnt, num ; struct tagNODE * fail, * child[CHARNUM] ; } NODE ; #define root stack[0] NODE * tmp, * tmpFail, * newNode, * parntNode, * childNode ; NODE * queue[LESSMAX * 1000], * stack[LESSMAX * 1000] ; int stkPtr ; // for stack int head, tial ; // for queue int n ; int count[1001] ; char pattn[1001][LESSMAX], model[MAXSIZE] ; void makeTrie (char * ptn, int num) { int i, j ; int len = strlen (ptn) ; tmp = root ; for (i = 0 ; i < len ; ++i) { j = ptn[i] - 'A' ; if (!tmp->child[j]) { newNode = (NODE *) calloc (1, sizeof (NODE)) ; stack[stkPtr++] = newNode ; tmp->child[j] = newNode ; } tmp = tmp->child[j] ; } tmp->num = num ; ++tmp->cnt ; } void makeFail () { int i, j ; head = tial = 0 ; for (i = 0 ; i < CHARNUM ; ++i) { if (root->child[i]) { root->child[i]->fail = root ; queue[tial++] = root->child[i] ; } } while (head < tial) { parntNode = queue[head++] ; for (i = 0 ; i < CHARNUM ; ++i) { if (childNode = parntNode->child[i]) { tmpFail = parntNode->fail ; while (tmpFail != root && !tmpFail->child[i]) tmpFail = tmpFail->fail ; // 上一步没有对root的孩子检查是否与childNode匹配 // 所以这一步这检查一下,不能这样: // (tmp == root) ? root : tmpFail->child[i] ; childNode->fail = (tmpFail->child[i]) ? tmpFail->child[i] : root ; // 最后一步,不要忘了 queue[tial++] = childNode ; } } } } void ACAutomation () { int i, j ; int len = strlen (model) ; memset (count, 0, sizeof (count)) ; tmp = root ; for (i = 0 ; i < len ; ++i) { if ('A' <= model[i] && model[i] <= 'Z') { j = model[i] - 'A' ; while (!tmp->child[j] && tmp != root) tmp = tmp->fail ; // root 的child中有没有可以匹配的项,目前还是不知道的 // 所以下面还要再判断一下, 如果tmp 的child 能匹配到, // 则无论tmp 是什么都可以直接用,否则就要它就是一定 // 是root。这一句由于有两种实现方法,在不看答案代码 // 的时候,我曾经错误地写成: // (tmp == root) ? root : tmp->child[j] // 实际上,当tmp == root 的时候,tmp->child[j] 可能 // 是能够匹配的,而错误的语句却仍然把root 赋给了tmp tmp = (tmp->child[j]) ? tmp->child[j] : root ; tmpFail = tmp ; while (tmpFail->cnt) { ++count[tmpFail->num] ; // tmpFail->cnt = 0 ; tmpFail = tmpFail->fail ; } } else { /* 这句一定要加,否则当出现这样的数据的时候,便会错误: ----------------------------------------------------------------------- 3 AA BB CC A%AB%BC^&CC 正确输出: CC: 1 错误输出: AA: 1 BB: 1 CC: 2 ----------------------------------------------------------------------- 为什么会这样呢? 因为它会认为A%A是连续的! 所以当出现非英文大写字符时,便要从根部重新开始匹配了! 当然,不加这句也可以,前提是CHARNUM 要变成128 个! 并且要在相应的地方进行修改,这样的话,由于child的数目 增多了,循环的负担也会相应变大,时间自然有所增加! */ tmp = root ; } } } void recycle () { while (stkPtr) free (stack[--stkPtr]) ; } int main () { int i, j ; while (scanf ("%d", &n) != EOF) { stkPtr = 1 ; stack [0] = (NODE *) calloc (1, sizeof (NODE)) ; for (i = 1 ; i <= n ; ++i) { scanf ("%s", pattn[i]) ; getchar () ; makeTrie (pattn[i], i) ; } scanf ("%s", model) ; makeFail () ; ACAutomation () ; for (i = 1 ; i <= n ; ++i) { if (count[i]) { printf ("%s: %d\n", pattn[i], count[i]) ; } } recycle () ; } return 0 ; }