病毒侵袭 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修改太多,动态分配新节点可以节约很多空间
看来模板强度还要再升级呀。。