病毒侵袭 HDU - 2896 newnode型自动机

题意:

含有特征串的字符串有病毒,给一堆特征串,按顺序判定一组字符串是否有病毒

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e4+7;
const int maxm=210;
const int maxnode=205*500;
const int sigma=98;

char ori[maxn];
int n,m;

struct automata{
	int ch[maxnode][sigma];
	int val[maxnode];
	int f[maxnode];
	//int last[maxnode];
	int clude[510];
	int sz,root;

	int newnode(){
		memset(ch[sz],0,sizeof(ch[sz]));
		f[sz]=0;
		val[sz++]=0;
		return sz-1;
	}

	void init(){
		sz=0;
		root=newnode();
	}

	void insert(char* s,int v){
		int u=root;
		for(int i=0;s[i];i++){
			int id=s[i]-30;
			if(!ch[u][id]){
				ch[u][id]=newnode();
				//memset(ch[sz],0,sizeof(ch[sz]));
				//val[sz++]=0;
			}
			u=ch[u][id];
		}
		val[u]+=v;
	}

	void build(){
		queue<int>q;
		//last[0]=f[0]=0;
		f[0]=0;
		for(int i=0;i<sigma;i++){
			int u=ch[0][i];
			if(u){
				//f[u]=last[u]=0;
				f[u]=0;
				q.push(u);
			}
		}
		while(!q.empty()){
			int now=q.front();q.pop();
			for(int i=0;i<sigma;i++){
				int u=ch[now][i];
				if(!u)continue;
				q.push(u);
				int v=f[now];
				while(v&&!ch[v][i])v=f[v];
				f[u]=ch[v][i];
				//last[u]=val[f[u]]?f[u]:last[f[u]];
			}
		}
	}
	
	int find(char* s,int number){
		memset(clude,0,sizeof(clude));
		int j=0;
		int flag=0;
		for(int i=0;s[i];i++){
			int id=s[i]-30;
			while(j&&!ch[j][id])j=f[j];
			j=ch[j][id];
			if(val[j]){
				clude[val[j]]=1;
				flag=1;
			}
		}
		if(!flag)return 0;
		else{
			printf("web %d:",number);
			for(int i=1;i<=n;i++){
				if(clude[i])printf(" %d",i);
			}
			printf("\n");
			return 1;
		}
	}
}ac;

int main(){
	while(~scanf("%d",&n)){
		ac.init();
		for(int i=1;i<=n;i++){
			scanf("%s",ori);
			ac.insert(ori,i);
		}
		ac.build();
		scanf("%d",&m);

		int ans=0;
		for(int i=1;i<=m;i++){
			scanf("%s",ori);
			if(ac.find(ori,i))ans++;
		}
		printf("total: %d\n",ans);

	}
}

错了十来发,得到以下教训:OJ的空间取决于修改了多少而不是创建了多少,原本的一次memset修改太多,动态分配新节点可以节约很多空间

看来模板强度还要再升级呀。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值