1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
先输入N个串,再输入M个串,对前N个串中的每个串输出后面M个串在它上面匹配了多少次。
把后M个串建立AC自动机,val[u]表示以u这个结点为结尾时匹配了几个串,别忘了val[u]+=val[f[u]]。然后对前N个串分别find,复杂度是所有字符串的长度和。
#include<cstring> #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<queue> #define INF 0x3f3f3f3f #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long LL; const int SIGMA_SIZE=26; const int MAXN=100010; const int MAXNODE=600010; const LL MOD= 258280327; int T,N,M; LL ans; string str1[MAXN],str2[MAXN]; struct AC{ int ch[MAXNODE][SIGMA_SIZE],f[MAXNODE],sz; LL val[MAXNODE]; void init(){ memset(ch[0],0,sizeof(ch[0])); val[0]=0; sz=1; } int idx(char c){ return c-'a'; } void insert(string s){ int u=0,len=s.size(); for(int i=0;i<len;i++){ int c=idx(s[i]); if(!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]++; } void get_fail(){ queue<int> q; f[0]=0; for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[0][c]; if(u){ f[u]=0; q.push(u); } } while(!q.empty()){ int r=q.front(); q.pop(); for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[r][c]; if(!u){ ch[r][c]=ch[f[r]][c]; continue; } q.push(u); f[u]=ch[f[r]][c]; val[u]+=val[f[u]]; } } } void find(string T){ int j=0; int len=T.size(); for(int i=0;i<len;i++){ int c=idx(T[i]); j=ch[j][c]; ans+=val[j]; } } }ac; int main(){ freopen("in.txt","r",stdin); scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) cin>>str1[i]; for(int i=1;i<=M;i++) cin>>str2[i]; ac.init(); for(int i=1;i<=M;i++) ac.insert(str2[i]); ac.get_fail(); for(int i=1;i<=N;i++){ ans=0; ac.find(str1[i]); printf("%I64d\n",ans); } } return 0; }