杭电 hdu 3065 病毒侵袭持续中

/* 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 ;
}

你可能感兴趣的:(ACM,pyy,AC自动机)