#include <bits/stdc++.h>   using namespace std;   const int SIGMA_SIZE = 26;   const int MAXNODE = 1000010;   struct AhoCorasickAutomata {     int ch[MAXNODE][SIGMA_SIZE];     int f[MAXNODE];     int match[MAXNODE];     int mp[MAXNODE];     int sz;     void init() { sz = 1; }     int idx(char c) {       if (c <=  z  && c >=  a )         return c -  a ;       else         return 0;     }     void insert(char *s, int v) {       int u = 0, n = strlen(s);       for (int i = 0; i < n; i++) {         int c = idx(s[i]);         if (!ch[u][c]) {           ch[u][c] = sz++;         }         u = ch[u][c];       }       match[u] = 1;       mp[v] = u;     }     void getFail() {       queue<int> q;       f[0] = 0;       for (int c = 0; c < SIGMA_SIZE; c++) {         int u = ch[0][c];         if (u) {           f[u] = 0;           q.push(u);         }       }       while (!q.empty()) {         int r = q.front();         q.pop();         for (int c = 0; c < SIGMA_SIZE; c++) {           int u = ch[r][c];           if (!u) {             ch[r][c] = ch[f[r]][c];             continue;           }           q.push(u);           int v = f[r];           while (v && !ch[v][c]) v = f[v];           f[u] = ch[v][c];         }       }     }   };   AhoCorasickAutomata ac;   vector<int> edge[MAXNODE];   char str[MAXNODE];   bool flag[MAXNODE];   int L[MAXNODE];   int R[MAXNODE];   int tot;   struct node {     int l, r;   };   struct Segtree {     int add[MAXNODE << 2], sum[MAXNODE << 2];     node seg[MAXNODE << 2];     void build(int o, int l, int r) {       seg[o].l = l, seg[o].r = r;       if (l == r) return;       int m = (l + r) >> 1;       build(o << 1, l, m);       build(o << 1 | 1, m + 1, r);     }     void pushdown(int o) {       if (add[o]) {         int len = seg[o].r - seg[o].l + 1;         add[o << 1] += add[o];         add[o << 1 | 1] += add[o];         sum[o << 1] += add[o] * (seg[o << 1].r - seg[o << 1].l + 1);         sum[o << 1 | 1] += add[o] * (seg[o << 1 | 1].r - seg[o << 1 | 1].l + 1);         add[o] = 0;       }     }     void pushup(int o) { sum[o] = sum[o << 1] + sum[o << 1 | 1]; }     void update(int o, int l, int r, int val) {       if (l <= seg[o].l && seg[o].r <= r) {         add[o] += val;         sum[o] += val;         return;       }       pushdown(o);       int m = (seg[o].l + seg[o].r) >> 1;       if (l <= m) update(o << 1, l, r, val);       if (r > m) update(o << 1 | 1, l, r, val);       pushup(o);     }     int query(int o, int pos) {       if (seg[o].l == seg[o].r) return sum[o];       pushdown(o);       int m = (seg[o].l + seg[o].r) >> 1;       if (pos <= m) return query(o << 1, pos);       if (pos > m) return query(o << 1 | 1, pos);     }   } tree;   void dfs(int u) {     L[u] = ++tot;     for (int i = 0; i < edge[u].size(); i++) {       int v = edge[u][i];       dfs(v);     }     R[u] = tot;   }   int main() {     ios::sync_with_stdio(false);     int n, k;     while (cin >> n >> k) {       ac.init();       for (int i = 0; i < k; i++) {         cin >> str;         ac.insert(str, i + 1);       }       ac.getFail();       memset(flag, 1, sizeof(flag));       for (int i = 1; i <= ac.sz; i++) edge[ac.f[i]].push_back(i);       dfs(0);       tree.build(1, 1, ac.sz);       for (int i = 1; i <= ac.sz; i++) {         if (ac.match[i]) {           tree.update(1, L[i], R[i], 1);         }       }       while (n--) {         cin >> str;         int len = strlen(str);         if (str[0] ==  ? ) {           int u = 0, ans = 0;           for (int i = 1; i < len; i++) {             int c = ac.idx(str[i]);             u = ac.ch[u][c];             ans += tree.query(1, L[u]);           }           cout << ans << endl;         }         if (str[0] ==  + ) {           int num = 0;           for (int i = 1; i < len; i++) {             num = num * 10 + str[i] -  0 ;           }           if (flag[num]) continue;           flag[num] = 1;           tree.update(1, L[ac.mp[num]], R[ac.mp[num]], 1);         }         if (str[0] ==  - ) {           int num = 0;           for (int i = 1; i < len; i++) {             num = num * 10 + str[i] -  0 ;           }           if (!flag[num]) continue;           flag[num] = 0;           tree.update(1, L[ac.mp[num]], R[ac.mp[num]], -1);         }       }     }   }