# hdu 5384 Danganronpa（AC自动机）

## 题意：

f(A,B)表示：B在A中作为子串出现的次数。

Ai是证据，Bi是子弹，题目问：所有Bi对每个Ai造成的伤害是多少，即每个Bi在Ai中出现的次数总和。

## 解析：

my$my$ code$code$

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
const int MAXN = (int)1e5 + 10;
const int maxnode = (int)1e5 + 10;
const int sigma_size = 26;

struct AC {
int ch[maxnode][sigma_size];
int fail[maxnode];
int last[maxnode];
int val[maxnode];
int sz;
int ans;

void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }

inline int idx(char c) { return c - 'a'; }

void insert(char *s) {
int u = 0, n = strlen(s);
for(int i = 0; i < n; 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]++;
}

int getFail() {
queue<int> que;
for(int c = 0; c < sigma_size; c++) {
int u = ch[0][c];
if(u) { fail[u] = 0; que.push(u); last[u] = 0; }
}
while(!que.empty()) {
int r = que.front(); que.pop();
for(int c = 0; c < sigma_size; c++) {
int u = ch[r][c];
if(!u) continue;
que.push(u);
int v = fail[r];
while(v && !ch[v][c]) v = fail[v];
fail[u] = ch[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}

int find(const char* tar) {
int n = strlen(tar);
int v = 0;
ans = 0;
for(int i = 0; i < n; i++) {
int c = idx(tar[i]);
while(v && !ch[v][c]) v = fail[v];
v = ch[v][c];
if(val[v]) print(v);
else if(last[v]) print(last[v]);
}
return ans;
}

void print(int j) {
while(j) {
ans += val[j];
j = last[j];
}
}
} ac;

string tar[MAXN];
char key[MAXN];

int n, m;
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
ac.clear();
for(int i = 0; i < n; i++) {
cin >> tar[i];
}
for(int i = 0; i < m; i++) {
scanf("%s", key);
ac.insert(key);
}
ac.getFail();
for(int i = 0; i < n; i++) {
printf("%d\n", ac.find( tar[i].c_str() ));
}
}
return 0;
}