#include <bits/stdc++.h>
using namespace std;
const int Max = 1111111, Maxk = 111111;
struct Node {
  Node *c[26], *fail;
} pool_node[Max], *tail_node = pool_node, *Root, *pos[Maxk];
inline int getid(Node *v) { return v - pool_node; }
struct Edge {
  int v;
  Edge *nxt;
} pool_edge[Max], *tree[Max], *tail_edge = pool_edge;
inline void addedge(const int &u, const int &v) {
  tail_edge->v = v;
  tail_edge->nxt = tree[u], tree[u] = tail_edge++;
}
class Binary_index_tree {
 private:
  int n, a[Max * 2];

 public:
  inline void init(const int &size) { n = size; }
  void add(const int &t, const int &delta) {
    for (int i = t; i <= n; i += i & -i) {
      a[i] += delta;
    }
  }
  int query(const int &t) const {
    int ret = 0;
    for (int i = t; i >= 1; i &= i - 1) {
      ret += a[i];
    }
    return ret;
  }
} b;
int n, k, in[Max], out[Max], cur;
bool outgov[Max];
Node *insert(Node *&root, char *s) {
  if (!root) {
    root = tail_node++;
  }
  if (!*s) {
    return root;
  } else {
    return insert(root->c[*s - 'a'], s + 1);
  }
}
void getfail() {
  static Node *q[Max];
  int l = 1, r = 0;
  for (int i = 0; i < 26; ++i) {
    if (Root->c[i]) {
      q[++r] = Root->c[i];
      q[r]->fail = Root;
      addedge(getid(Root), getid(q[r]));
    } else {
      Root->c[i] = Root;
    }
  }
  while (l <= r) {
    for (int i = 0; i < 26; ++i) {
      if (q[l]->c[i]) {
        q[++r] = q[l]->c[i];
        q[r]->fail = q[l]->fail->c[i];
        addedge(getid(q[r]->fail), getid(q[r]));
      } else {
        q[l]->c[i] = q[l]->fail->c[i];
      }
    }
    ++l;
  }
}
void dfs(int u) {
  in[u] = ++cur;
  for (Edge *p = tree[u]; p; p = p->nxt) {
    dfs(p->v);
  }
  out[u] = ++cur;
}
int getans(Node *root, char *s) {
  if (!*s) {
    return b.query(in[getid(root)]);
  } else {
    return b.query(in[getid(root)]) + getans(root->c[*s - 'a'], s + 1);
  }
}
int main() {
  scanf("%d%d", &n, &k);
  for (int i = 1; i <= k; ++i) {
    static char st[Max];
    scanf("%s", st);
    pos[i] = insert(Root, st);
  }
  getfail();
  dfs(0), b.init(cur + 1);
  for (int i = 1; i <= k; ++i) {
    b.add(in[getid(pos[i])], 1), b.add(out[getid(pos[i])] + 1, -1);
  }
  while (n--) {
    static char opt[Max];
    scanf("%s", opt);
    if (*opt == '?') {
      printf("%d\n", getans(Root, opt + 1));
    } else {
      int v;
      char c;
      sscanf(opt, "%c%d", &c, &v);
      if (c == '+' && outgov[v]) {
        b.add(in[getid(pos[v])], 1), b.add(out[getid(pos[v])] + 1, -1);
        outgov[v] = false;
      }
      if (c == '-' && !outgov[v]) {
        b.add(in[getid(pos[v])], -1), b.add(out[getid(pos[v])] + 1, 1);
        outgov[v] = true;
      }
    }
  }
  return 0;
}
