题意:n个A,m个B,对于每个A,输出所有B在A中出现的次数
思路:和AC自动机模版题2222相同,唯一的区别就是n个A不能开二维,自己处理一下就OK了
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=500010; const int N=26; struct node{ node *fail; node *next[N]; int num; node(){ fail=NULL; num=0; memset(next,NULL,sizeof(next)); } }*q[maxn]; char str1[100010],str2[10010],str[10010]; int tmp[100010]; int head,tail; void insert_Trie(char *str,node *root){ node *p=root; int i=0; while(str[i]){ int id=str[i]-'a'; if(p->next[id]==NULL) p->next[id]=new node(); p=p->next[id];i++; } p->num++; } void build_ac(node *root){ root->fail=NULL; q[head++]=root; while(head!=tail){ node *temp=q[tail++]; node *p=NULL; for(int i=0;i<N;i++){ if(temp->next[i]!=NULL){ if(temp==root) temp->next[i]->fail=root; else{ p=temp->fail; while(p!=NULL){ if(p->next[i]!=NULL){ temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=root; } q[head++]=temp->next[i]; } } } } int query(node *root,char str2[]){ int i=0,ans=0; node *p=root; while(str2[i]){ int id=str2[i]-'a'; while(p->next[id]==NULL&&p!=root) p=p->fail; p=p->next[id]; p=(p==NULL)?root:p; node *temp=p; while(temp!=root&&temp->num!=-1){ ans+=temp->num; temp=temp->fail; } i++; } return ans; } void del(node *p){ if(p==NULL)return ; for(int i=0;i<26;i++)del(p->next[i]); delete p; } int main(){ int T,n,m; scanf("%d",&T); while(T--){ node *root=new node(); head=tail=0; scanf("%d%d",&n,&m); int k=0; for(int i=0;i<n;i++){ scanf("%s",str); int len=strlen(str); tmp[i]=len; for(int j=0;j<len;j++) str1[k++]=str[j]; } for(int i=0;i<m;i++){ scanf("%s",str2); insert_Trie(str2,root); } build_ac(root);k=0; for(int i=0;i<n;i++){ for(int j=0;j<tmp[i];j++) str[j]=str1[k++]; str[tmp[i]]='\0'; int ans=query(root,str); printf("%d\n",ans); } del(root); } return 0; }
时间: 2024-10-06 23:46:39