#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);
      }
    }
  }
}
