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 ", ac.find(s1[i])); } } return 0; }