constint M = 26; classacAutomaton { private: std::vector<std::vector<int> > ne; std::vector<std::vector<int> > end; std::vector<int> p; int idx = 0; int num = 0; intadd(){ ne.push_back(std::vector<int>(M, 0)); end.push_back(std::vector<int>()); return idx++; } voidcalcPre(){ p.resize(idx); p[0] = 0; std::queue<int> q; for (int i = 0; i < M; ++i) { if (ne[0][i]) q.push(ne[0][i]); // 注意,直接插入根节点会出现和KMP一样的问题 }
while (!q.empty()) { int u = q.front(); q.pop(); for (int i = 0; i < M; ++i) { int& v = ne[u][i]; if (v) { p[v] = ne[p[u]][i]; // 上一个可以的地方 q.push(v); } else { v = ne[p[u]][i]; // 直接插到上一个可以的地方 } } }
// for (int i = 0; i < idx; ++i) { // // for (int j = 0; j < M; ++j) { // // printf("i = %d, j = %d, ne = %d\n", i, j, ne[i][j]); // // } // // printf(">>i = %d, p = %d\n", i, p[i]); // } } public: acAutomaton() {add(); } voidaddToTrie(const std::string& s){ int now = 0; for (constchar& c : s) { if (!ne[now][c - 'a']) ne[now][c - 'a'] = add(); now = ne[now][c - 'a']; // end[now] = (&c == &s.back() ? ++num : 0); if (&c == &s.back()) end[now].push_back(num++); // if (end[now]) printf("end %d = %d\n", now, end[now]); } } std::vector<int> calc(const std::string& t){ calcPre(); std::vector<int> vis(idx, 0); int u = 0; for (constchar c : t) { while (u && !ne[u][c - 'a']) u = p[u]; u = ne[u][c - 'a']; vis[u] ++; }
// for (int i = 1; i < idx; ++i) { // int j = i; // if (!vis[j]) continue; // while (p[j]) j = p[j], vis[j] += vis[j]; // }
std::vector<int> d(idx, 0); std::queue<int> q; for (int i = 1; i < idx; ++i) { d[p[i]]++; } for (int i = 1; i < idx; ++i) { if (!d[i]) q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); if (!u) continue; int v = p[u]; vis[v] += vis[u]; --d[v]; if (!d[v]) q.push(v); }
std::vector<int> res(num); for (int i = 1; i < idx; ++i) { // printf("vis[%d] = %d\n", i, vis[i]); if (end[i].empty()) continue; for (constint j : end[i]) res[j] = vis[i]; } return res; } };
signedmain(){ int n; std::cin >> n; acAutomaton T; for (int i = 0; i < n; ++i) { std::string s; std::cin >> s; T.addToTrie(s); } std::string t; std::cin >> t; for (constauto x : T.calc(t)) std::cout << x << std::endl; return0; }