#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LOCAL #include "debug.h" #else #define debug(x...) #endif /* #pragma GCC optimize("Ofast") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") */ //#define int ll using namespace std; typedef long long ll; typedef long double ld; typedef pair < int, int > pii; typedef pair < ll, ll > pll; #define sz(x) int((x).size()) #ifndef LOCAL mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); #else mt19937 rng(228); #endif const int N = 3e4 + 7; const int inf = INT_MAX / 2; const ll INF = LLONG_MAX / 3; const int MOD = 1e9 + 7; const double eps = 1e-6; const string cars[] = {"🚗", "🚕", "🚙"}; vector < int > solve1(vector < string >& t, vector < string >& s) { vector < int > res(sz(s)); for (int i = 0; i < sz(s); i++) { for (int j = 0; j < sz(t); j++) { if (t[j].substr(0, sz(s[i])) == s[i] && t[j].substr(sz(t[j]) - sz(s[i])) == s[i]) { res[i]++; } } } return res; } int n, m; struct Tree { vector < ll > t[4 * N]; Tree() {} void init(vector < ll >& a) { for (auto& x : t) { x.clear(); } build(1, 0, sz(a) - 1, a); } void build(int v, int tl, int tr, vector < ll >& a) { if (tl == tr) { t[v].push_back(a[tl]); } else { int tm = (tl + tr) / 2; build(2 * v, tl, tm, a); build(2 * v + 1, tm + 1, tr, a); merge(t[2 * v].begin(), t[2 * v].end(), t[2 * v + 1].begin(), t[2 * v + 1].end(), back_inserter(t[v])); } } int query(int v, int tl, int tr, int l, int r, ll val) { if (l > r) { return 0; } if (tl == l && tr == r) { auto [L, R] = equal_range(t[v].begin(), t[v].end(), val); return R - L; } else { int tm = (tl + tr) / 2; return query(2 * v, tl, tm, l, min(r, tm), val) + query(2 * v + 1, tm + 1, tr, max(tm + 1, l), r, val); } } } tree[52]; void binsearch(vector < string >& t, string& s, int& l, int& r) { int L = 0, R = sz(t), M; while (R - L > 1) { M = (L + R) / 2; string a = t[M].substr(0, sz(s)); if (s <= a) { R = M; } else { L = M; } } if (s < t[L].substr(0, sz(s))) { l = 1, r = 0; return; } l = (s <= t[L].substr(0, sz(s)) ? L : R); L = 0, R = sz(t); while (R - L > 1) { M = (L + R) / 2; string a = t[M].substr(0, sz(s)); if (s >= a) { L = M; } else { R = M; } } r = (R != sz(t) && s >= t[R].substr(0, sz(s)) ? R : L); } vector < int > solve2(vector < string > t, vector < string > s) { sort(t.begin(), t.end()); //debug(t); vector < vector < ll > > h(sz(t)); for (int j = 0; j < sz(t); j++) { h[j].resize(sz(t[j])); h[j].back() = t[j].back() - 'a' + 1; for (int i = sz(t[j]) - 2; i >= 0; i--) { h[j][i] = h[j][i + 1] * 229 + (t[j][i] - 'a' + 1); } } for (int j = 1; j <= 50; j++) { vector < ll > a(sz(t)); for (int i = 0; i < sz(t); i++) { if (sz(t[i]) - j >= 0) { a[i] = (h[i][sz(t[i]) - j]); } } tree[j].init(a); } vector < int > res(sz(s)); for (int i = 0; i < sz(s); i++) { int l, r; binsearch(t, s[i], l, r); //debug(l, r); if (l > r) { continue; } ll h = s[i].back() - 'a' + 1; for (int j = sz(s[i]) - 2; j >= 0; j--) { h = h * 229 + s[i][j] - 'a' + 1; } res[i] = tree[sz(s[i])].query(1, 0, sz(t) - 1, l, r, h); } return res; } int rng_on(int l, int r) { return rng() % (r - l + 1) + l; } signed main() { #ifdef LOCAL freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif cout << fixed << setprecision(4); ios::sync_with_stdio(false); cin.tie(); cout.tie(); ///* cin >> n; vector < string > t(n); for (string& x : t) { cin >> x; } cin >> m; vector < string > s(m); for (string& x : s) { cin >> x; } auto ans = solve2(t, s); for (int x : ans) { cout << x << "\n"; } return 0; //*/ for (int it = 0; ; it++) { int n = rng_on(1, 10); int m = rng_on(1, 1); vector < string > t(n), s(m); for (string& x : t) { int len = rng_on(1, 10); for (int i = 0; i < len; i++) { x.push_back('a' + rng_on(0, 4)); } } for (string& x : s) { int len = rng_on(1, 10); for (int i = 0; i < len; i++) { x.push_back('a' + rng_on(0, 4)); } } auto s1 = solve1(t, s); auto s2 = solve2(t, s); if (s1 != s2) { debug(it); debug(t); debug(s); debug(s1); debug(s2); return 0; } } return 0; }