题意:
含有特征串的字符串有病毒,给一堆特征串,按顺序判定一组字符串是否有病毒
代码:
#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修改太多,动态分配新节点可以节约很多空间
看来模板强度还要再升级呀。。