1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
真真是没见过这么简单的多校了,然而并不能做对orz 这个题说明了模板的重要性
#include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; #define N 100010 #define M 26 #define X 10010 char sentencea[N][X]; char worda[X]; struct AC{ int nexta[N][M]; int faila[N]; int enda[N]; int L; int root; int newnode(){ for(int i=0;i<M;i++){ nexta[L][i]=-1; } enda[L++]=0; return L-1; } void init(){ L=0; root=newnode(); } void assert(char word[]){ int now=root; for(int i=0;word[i]!='\0';i++){ int tempch=word[i]-'a'; if(nexta[now][tempch]==-1){ nexta[now][tempch]=newnode(); } now=nexta[now][tempch]; } enda[now]++; } void build(){ queue<int> q; for(int i=0;i<M;i++){ if(nexta[root][i]==-1){ nexta[root][i]=root;//nexta[root][i]都不存在了,哪还有什么root一直到nexta[root][i]都相等这一说,所以当然不存在fail[nexta[root][i]]?乖,回去重新比较! } else{ faila[nexta[root][i]]=root;//这里nexta[root][i]已经非-1了,不需要重新赋值,但是由于nexta[root][i]是存在的所以存在一种可能从root一直到nexta[root][i]一直相等,所以好吧,给你个fail[nexta[root][i]] q.push(nexta[root][i]); } } while(!q.empty()){ int temp=q.front(); q.pop(); for(int i=0;i<M;i++){ if(nexta[temp][i]==-1){ nexta[temp][i]=nexta[faila[temp]][i]; } else{ faila[nexta[temp][i]]=nexta[faila[temp]][i]; q.push(nexta[temp][i]); } } } } int query(char sentence[]){ int now=root; long long int ans=0; for(int i=0;sentence[i]!='\0';i++){ now=nexta[now][sentence[i]-'a']; int temp=now; while(temp!=root){ ans+=enda[temp]; temp=faila[temp]; } } return ans; } }; AC ac; int main(){ // freopen("cin.txt","r",stdin); int t; int n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); ac.init(); for(int i=0;i<n;i++){ scanf("%s",sentencea[i]); } for(int i=0;i<m;i++){ scanf("%s",worda); ac.assert(worda); } ac.build(); for(int i=0;i<n;i++){ printf("%d\n",ac.query(sentencea[i])); } } return 0; }