| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 
 | #include <iostream>#include <cstring>
 #include <vector>
 #define maxn 100010
 #define Maxn 200010
 #define maxm 360010
 #define ll long long
 using namespace std;
 
 int n, m, pos[maxn];
 
 char s[maxn], c[maxm];
 
 struct SAM {
 struct node {
 int l, L, nxt[26], cnt;
 } T[Maxn]; int f[Maxn], top, rt, last;
 void init() {
 rt = last = top = 1;
 T[rt].L = T[rt].l = f[rt] = 0;
 }
 
 int extend(int p, int ch) {
 if (T[p].nxt[ch]) {
 int q = T[p].nxt[ch], nq;
 if (T[q].L - 1 == T[p].L) return q;
 nq = ++top; T[nq].L = T[p].L + 1; f[nq] = f[q];
 for (int i = 0; i < 26; ++i) T[nq].nxt[i] = T[q].nxt[i];
 while (p && T[p].nxt[ch] == q) T[p].nxt[ch] = nq, p = f[p];
 f[q] = nq; return nq;
 }
 int np = ++top; T[np].L = T[p].L + 1;
 while (p && !T[p].nxt[ch]) T[p].nxt[ch] = np, p = f[p];
 if (!p) return f[np] = rt, np;
 int q = T[p].nxt[ch];
 if (T[q].L - 1 == T[p].L) f[np] = q;
 else {
 int nq = ++top; T[nq].L = T[p].L + 1; f[nq] = f[q];
 for (int i = 0; i < 26; ++i) T[nq].nxt[i] = T[q].nxt[i];
 while (p && T[p].nxt[ch] == q) T[p].nxt[ch] = nq, p = f[p];
 f[np] = f[q] = nq;
 }
 return np;
 }
 
 void insert(char *s) {
 int l = strlen(s), p = rt;
 for (int i = 0; i < l; ++i) p = extend(p, s[i] - 'a');
 }
 } SAM;
 
 struct SegmentTree {
 #define lc T[i].ch[0]
 #define rc T[i].ch[1]
 #define Lc T[j].ch[0]
 #define Rc T[j].ch[1]
 struct node {
 int v, ch[2];
 } T[Maxn * 20]; int rt[Maxn], top;
 inline void maintain(int i) { T[i].v = T[lc].v + T[rc].v; }
 
 void update(int &i, int l, int r, int k, int v) {
 if (!i) i = ++top;
 if (l == r) return T[i].v = v, void();
 int m = l + r >> 1;
 if (k <= m) update(lc, l, m, k, v);
 else update(rc, m + 1, r, k, v);
 maintain(i);
 }
 
 void merge(int &i, int j, int l, int r) {
 if (!i) return i = j, void();
 if (!j) return ;
 if (l == r) return T[i].v |= T[j].v, void();
 int m = l + r >> 1;
 merge(lc, Lc, l, m); merge(rc, Rc, m + 1, r);
 maintain(i);
 }
 } Seg;
 
 struct Edge {
 int to, next;
 } e[Maxn]; int head[Maxn], c1;
 inline void add_edge(int u, int v) {
 e[c1].to = v; e[c1].next = head[u]; head[u] = c1++;
 }
 
 vector<int> A[Maxn];
 void solve(int k, int l, int r) {
 int p = SAM.rt;
 for (int i = l; i <= r; ++i) {
 p = SAM.T[p].nxt[s[i] - 'a'];
 A[p].push_back(k);
 }
 }
 
 void dfs(int u) {
 for (auto t : A[u]) Seg.update(Seg.rt[u], 1, n, t, 1);
 for (int i = head[u]; ~i; i = e[i].next) {
 int v = e[i].to; dfs(v);
 Seg.merge(Seg.rt[u], Seg.rt[v], 1, n);
 } SAM.T[u].cnt = Seg.T[Seg.rt[u]].v;
 }
 
 int match(char *s) {
 int l = strlen(s), p = SAM.rt;
 for (int i = 0; i < l; ++i) p = SAM.T[p].nxt[s[i] - 'a'];
 return SAM.T[p].cnt;
 }
 
 int main() { fill(head, head + Maxn, -1);
 ios::sync_with_stdio(false);
 cin.tie(nullptr); cout.tie(nullptr);
 
 cin >> n >> m; SAM.init();
 for (int i = 1; i <= n; ++i) {
 cin >> s + pos[i];
 SAM.insert(s + pos[i]);
 pos[i + 1] = pos[i] + strlen(s + pos[i]);
 }
 for (int i = 1; i <= n; ++i) solve(i, pos[i], pos[i + 1] - 1);
 for (int i = 2; i <= SAM.top; ++i) add_edge(SAM.f[i], i); dfs(SAM.rt);
 for (int i = 1; i <= m; ++i) cin >> c, cout << match(c) << "\n";
 return 0;
 }
 
 
 |