1 2 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; }
|