http://acm.hdu.edu.cn/showproblem.php?pid=5384
/*
AC自动机是用来求多字符串匹配问题,所需要掌握的基础是KMP和trie
对匹配子串建立一棵trie树,对这棵树进行KMP匹配
*/
/************************************************
* Author :Powatr
* Created Time :2015-8-14 20:23:01
* File Name :HDU2222.cpp
************************************************/
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
string s1[MAXN], s2[MAXN];
struct AC{
int trie[MAXN][26], num[MAXN], fail[MAXN];
ll val[MAXN];
int pos;
void inti()
{
memset(trie, 0, sizeof(trie));
memset(val, 0, sizeof(val));
pos = 1;
}
void insert(string s)
{
int c = 0;
int len = s.size();
for(int i = 0; i < len; i++){
int m = s[i] - 'a';
if(!trie[c][m]){
memset(trie[pos], 0, sizeof(trie[pos]));
val[pos] = 0;
trie[c][m] = pos++;
}
c = trie[c][m];
}
val[c]++;
}
void get_fail()
{
queue<int> q;
fail[0] = 0;
for(int i = 0; i < 26; i++){
if(trie[0][i]){
fail[trie[0][i]] = 0;
q.push(trie[0][i]);
}
}
while(!q.empty()){
int r = q.front();
q.pop();
for(int i = 0; i < 26; i++){
int u = trie[r][i];
if(!u){
trie[r][i] = trie[fail[r]][i];
continue;
}
q.push(u);
fail[u] = trie[fail[r]][i];
val[u] += val[fail[u]];
}
}
}
long long find(string s)
{
ll ans = 0;
int len = s.size();
int j = 0;
for(int i = 0; i < len; i++){
int m = s[i] - 'a';
j = trie[j][m];
ans += val[j];
}
return ans;
}
}ac;
int main()
{
int T;
scanf("%d", &T);
int n, m;
while(T--){
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++) cin >> s1[i];
for(int i = 0; i < m; i++) cin >> s2[i];
ac.inti();
for(int i = 0 ; i < m; i++) ac.insert(s2[i]);
ac.get_fail();
for(int i = 0 ; i < n; i++){
printf("%I64d\n", ac.find(s1[i]));
}
}
return 0;
}