相当纠结~~
/* 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 ;
}