HDU 2896 病毒侵袭 AC自动机

   这道题是一道典型的AC自动机,如果对AC自动机了解的话,很容易就能A出来,如果你是用指针写的话,会出现超内存的错误,因为我刚开始就是用指针写的,然后又各种从网上百度,百度到所有用指针写的,复制粘贴上去都出现超内存的错误,后来用了静态数组谢了之后就过了。这道题卡的点也有输入跟输出这一块。

用指针写的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node {
	int count,index;
	node *fail;
	node *next[300];
	node() {
		index = 0;
		fail = 0;
		count=0;
		memset(next,0,sizeof(next));
	}
} *q[1000000];
int head=0,tail=0;
priority_queue<int, vector<int>, greater<int> > que;
node *root = new node(),*p1,*p2;
void insert(int num,char s[]) {
	int i=0;
	p1 = root;
	while(s[i]) {
		int val = (int)s[i] ;
		if(p1->next[val] == 0) {
			p2=new node();
			p1->next[val] = p2;
			p1 = p2;
		}
		else p1 = p1->next[val];
		i++;
	}
	p1->index= num;
	p1->count++;
}

void build_ac_automation() {
	root->fail = 0;
	q[head++] = root;
	while(head != tail) {
		p1 = q[tail++];
		for(int i=0; i<300; i++) {
			if(p1->next[i]) {
				if(p1 == root) p1->next[i]->fail = root;
				else {
					p2=p1->fail;
					while(p2) {
						if(p2->next[i]) {
							p1->next[i]->fail = p2->next[i];
							break;
						}
						p2 = p2->fail;
					}
					if(p2 == 0) p1->next[i]->fail = root;
				}
				q[head++] = p1->next[i];
			}
		}
	}
}

void query(char s[]) {
	int i=0;
	p1=root;
	while(s[i]) {
		int val = (int)s[i] ;
		while(p1->next[val]==0 && p1!=root) p1 = p1->fail;
		p1 = p1->next[val];
		p1 = (p1==0) ? root : p1;
		p2=p1;
		while(p2!=root && p2->count!=-1) {
			if(p2->count) 
				que.push(p2->index);
			p2->count=-1;
			p2 = p2->fail;
		}
		i++;
	}
}

int main() {
	int n,m,i,num=0;
	char s[505],st[10010];
	cin>>n;
	for(i=1; i<=n; i++) {
		cin>>s;
		insert(i,s);
	}
	cin>>m;
	build_ac_automation();
	for(i=1; i<=m; i++) {
		cin>>st;
		while(!que.empty()) que.pop();
		query(st);
		if(!que.empty()) {
			cout<<"web "<<i<<":";
			while(!que.empty()) {
				cout<<' '<<que.top();
				que.pop();
			}
			cout<<endl;
			num++;
		}
	}
	cout<<"total: "<<num<<endl;
	return 0;
}
用静态数组写的代码如下:

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node{
	int next[500*210][128],fail[500*210],vis[500*210];
	int sz,root;
	int newnode() {
		memset(next[sz],0,sizeof(next[sz]));
		vis[sz++] = 0;
		return sz-1;
	}
	void init() {
		sz=0;
		root = newnode();
	}
	void insert(char s[],int id) {
		int i,pre=root;
		for(i=0; s[i]; i++) {
			if(next[pre][s[i]] == 0)  {
				int now=newnode();
				next[pre][s[i]] = now;
				pre = now;
			}
			else pre = next[pre][s[i]];
		}
		vis[pre] = id;
	}
	
	void build_ac_automation() {
		queue<int> que;
		fail[root] = root;
		for(int i=0; i<128; i++) {
			if(next[root][i] == 0) next[root][i] = root;
			else {
				fail[next[root][i]] = root;
				que.push(next[root][i]);
			}
		}
		while(!que.empty()) {
			int temp=que.front();
			que.pop();
			for(int i=0; i<128; i++)  {
				if(next[temp][i]==0) {
					next[temp][i] = next[fail[temp]][i];
				}
				else {
					fail[next[temp][i]] = next[fail[temp]][i];
					que.push(next[temp][i]);
				}
			}
		}
	}
	
	int flag[520];
	int query(char s[]) {
		int i,ans=0;
		memset(flag,0,sizeof(flag));
		int temp=root;
		for(i=0; s[i]; i++) {
			temp=next[temp][s[i]];
			int p = temp;
			while(p!=root) {
				if(vis[p]) {
					flag[vis[p]] = 1;
					ans++;
				}
				p = fail[p];
			}
		}
		return ans;
	}
};
node ac;
int main() {
	int n,m,i,num=0;
	char s[210],str[10010];
	scanf("%d",&n);
	ac.init();
	for(i=1; i<=n; i++) {
		scanf("%s",s);
		ac.insert(s,i);
	}
	ac.build_ac_automation();
	scanf("%d",&m);
	for(i=0; i<m; i++) {
		scanf("%s",str);
		if(ac.query(str)) {
			printf("web %d:",i+1);
			num++;
			for(int j=0; j<520; j++) {
				if(ac.flag[j]) printf(" %d",j);
			}
			printf("\n");
		}
	}
	printf("total: %d\n",num);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值