hdu 2896 病毒来袭 ac_automaton

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=2896   

本题输出的时候需要排序,其余的是跟上一题差不多,不过不是技术,而是查看是否存在,所以如果该病毒存在,则记录在一个数组里,并不改变结点的数据。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int MAXN = 10000010;

struct Trie_Node
{
	int id;
	Trie_Node* fail;
	Trie_Node* pNext[100];
	Trie_Node()
	{
		id = 0;
		fail = NULL;
		memset(pNext, NULL, sizeof(pNext));
	}
};
Trie_Node* q[MAXN];
Trie_Node* proot;
int head, tail;

int cnt;
int arr[510];

void Insert_Trie(char* str, int id)
{
	Trie_Node* p = proot;
	for (; *str; str++)
	{
		int j = *str - 31;
		if (p->pNext[j] == NULL)
		{
			p->pNext[j] = new Trie_Node;
		}
		p = p->pNext[j];
	}
	p->id = id;
}

void Build_ac_automaton_fail()
{
	head = tail = 0;
	proot->fail = NULL;
	q[tail++] = proot;
	while (head != tail)
	{
		Trie_Node* temp = q[head++];
		Trie_Node* p = NULL;
		for(int i = 0; i < 100; ++i)
		{
			if(temp->pNext[i] != NULL)
			{
				if(temp == proot)
					temp->pNext[i]->fail = proot;
				else
				{
					p = temp->fail;
					while(p)
					{
						if (p->pNext[i] != NULL)
						{
							temp->pNext[i]->fail = p->pNext[i];
							break;
						}
						p = p->fail;
					}
					if(p == NULL)
						p = p->fail;
				}
				q[tail++] = temp->pNext[i];
			}
		}
	}
}

void Query_ac_automaton(char* str)
{
	cnt = 0;
	Trie_Node* p = proot;
	int i = 0;
	while (str[i])
	{
		int j = str[i] - 31;
		while(p->pNext[j] == NULL && p != proot)
			p = p->fail;
		p = (p->pNext[j] == NULL) ? proot : p->pNext[j];
		Trie_Node* temp = p;
		while(temp != proot)
		{
			if (temp->id)
			{
				arr[cnt++] = temp->id;
			}
			temp = temp->fail;
		}
		i++;
	}
}

char s1[10010], s2[210];
int main()
{
	int n,m;
	int i,j;
	while (~scanf("%d", &n))
	{
		proot = new Trie_Node;
		for(i = 1; i <= n; ++i)
		{
			scanf("%s", s2);
			Insert_Trie(s2, i);
		}

		Build_ac_automaton_fail();

		scanf("%d", &m);
		int total = 0;

		for(i = 1; i <= m; ++i)
		{
			memset(arr, 0, sizeof(arr));
			scanf("%s",s1);
			Query_ac_automaton(s1);
			if(cnt)
			{
				printf("web %d:", i);
				sort(arr, arr+cnt);
				for (j = 0; j < cnt; ++j)
					printf(" %d", arr[j]);
				printf("\n");
				total++;
			}
		}
		printf("total: %d\n",total);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值