病毒侵袭持续中
上一题是求出现多少病毒输出病毒序号,而这题输出每个病毒出现的次数。这题有字典树基础都能做出来,把叶子节点用相应的编号标记起来,匹配的时候遍历到叶子节点用一个数组把次数存起来就行了。 有了前几题的教训直接用静态树做用C++交,果然不会错!
const int N=129;
char str[2000001],s[1001][55],v[1001];
int head,tail,cnt;
struct tree
{int f;tree *fail;tree *next[N];
}*q[50001],*root,memory[50001];
void insert(int i,char *s)
{tree *p=root;while(*s!='\0'){int id=(int)(*s);if(p->next[id]==NULL) p->next[id]=&memory[cnt++];p=p->next[id];s++;}p->f=i;
}
void build()
{root->fail=NULL;q[head++]=root;while(head!=tail){tree *temp=q[tail++];tree *p=NULL;for(int i=0; i<N; i++)if(temp->next[i]){if(temp==root) temp->next[i]->fail=root;else{p=temp->fail;while(p!=NULL){if(p->next[i]){temp->next[i]->fail=p->next[i];break;}p=p->fail;}if(p==NULL) temp->next[i]->fail=root;}q[head++]=temp->next[i];}}
}
void find(char *s)
{tree *p=root;int ans=0;while(*s!='\0'){int id=(int)(*s);while(p->next[id]==NULL&&p!=root) p=p->fail;p=p->next[id];p=p==NULL?root:p;tree *temp=p;while(temp!=root){if(temp->f) v[temp->f]++;temp=temp->fail;}s++;}
}
int main()
{int n;while(~scanf("%d",&n)){memset(memory,0,sizeof(memory));memset(v,0,sizeof(v));cnt=head=tail=0;root=&memory[cnt++];for(int i=1; i<=n; i++){scanf("%s",s[i]);insert(i,s[i]);}build();scanf("%s",str);find(str);for(int i=1; i<=n; i++)if(v[i]) printf("%s: %d\n",s[i],v[i]);}return 0;
}