首页 > 其他 > 详细

HDU 3065 病毒侵袭持续中 AC自动机题解

时间:2014-08-07 23:06:35      阅读:483      评论:0      收藏:0      [点我收藏+]

其实本题比HDU的病毒侵袭1还简单,不过有一个陷阱卡到我了:就是搜索text的时候,当遇到的字母不是大写字母的时候,那么就要重新从根节点开始搜索,否则就会答案错误。

那么一点陷阱,居然没想到啊。

教训啊:看来对不太平常的地方,需要更加深入的思考,才能发现其中的陷阱,否则就WA了。


#include <stdio.h>
#include <string.h>
#include <queue>
using std::queue;

const int MAX_N = 1001;
const int VIRUS_LEN = 51;
const int TXT_LEN = 2000001;
const int ARR_SIZE = 26;
char Virus[MAX_N][VIRUS_LEN], txt[TXT_LEN];
int IdNum[MAX_N];

inline int getIndex(char a) { return a - 'A'; }

struct Node
{
	int n, num;
	Node *fail;
	Node *arr[ARR_SIZE];
};

Node pool[MAX_N*VIRUS_LEN], *Trie;
int poolID;

void clearNode(Node *rt)
{
	rt->n = rt->num = 0;
	rt->fail = NULL;
	memset(rt->arr, 0, sizeof(rt->arr));
}

void insert(char *w, int num)
{
	Node *pCrawl = Trie;
	for ( ; *w; w++)
	{
		int id = getIndex(*w);
		if (!pCrawl->arr[id])
		{
			pCrawl->arr[id] = &pool[poolID++];
			clearNode(pCrawl->arr[id]);
		}
		pCrawl = pCrawl->arr[id];
	}
	pCrawl->n++;
	pCrawl->num = num;
}

void buildFail()
{
	queue<Node *> qu;
	qu.push(Trie);
	while (!qu.empty())
	{
		Node *pCrawl = qu.front(); qu.pop();
		for (int i = 0; i < ARR_SIZE; i++)
		{
			if (!pCrawl->arr[i]) continue;
			pCrawl->arr[i]->fail = Trie;
			Node *fail = pCrawl->fail;
			while (fail)
			{
				if (fail->arr[i])
				{
					pCrawl->arr[i]->fail = fail->arr[i];
					break;
				}
				fail = fail->fail;
			}
			qu.push(pCrawl->arr[i]);
		}
	}
}

void search()
{
	Node *pCrawl = Trie;
	for (char *p = txt; *p; p++)
	{
		if (*p < 'A' || 'Z' < *p)
		{
			pCrawl = Trie;
			continue;
		}
		int id = getIndex(*p);
		while (!pCrawl->arr[id] && pCrawl != Trie) pCrawl = pCrawl->fail;
		if (pCrawl->arr[id])
		{
			pCrawl = pCrawl->arr[id];			
			for (Node *tmp = pCrawl; tmp && tmp->n; tmp = tmp->fail)
			{
				if (tmp->n) IdNum[tmp->num]++;
			}
		}
	}
}

int main()
{
	int n;
	Trie = &pool[0];
	while (scanf("%d", &n) != EOF)
	{
		getchar();
		clearNode(Trie);
		poolID = 1;
		
		for (int i = 0; i < n; i++)
		{
			gets(Virus[i]);
			insert(Virus[i], i);
		}
		buildFail();
		memset(IdNum, 0, sizeof(int) * n);

		gets(txt);
		search();
		
		for (int i = 0; i < n; i++)
		{
			if (IdNum[i]) printf("%s: %d\n",Virus[i], IdNum[i]); 
		}
	}
	return 0;
}



HDU 3065 病毒侵袭持续中 AC自动机题解,布布扣,bubuko.com

HDU 3065 病毒侵袭持续中 AC自动机题解

原文:http://blog.csdn.net/kenden23/article/details/38426581

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!