#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 100010, SIZE = 26, LEN = 1000010;
int n, m, dfk = 0;
namespace BIT {
int c[LEN];
void Add(int x, int k) {
  for (; x <= dfk; x += x & -x) c[x] += k;
  return;
}
int Sum(int x) {
  int sum = 0;
  for (; x; x -= x & -x) sum += c[x];
  return sum;
}
}  // namespace BIT
struct Trie_Node;
struct Edge;
struct Trie_Node {
  Trie_Node() {
    dfn = size = 0;
    head = NULL;
    fail = NULL;
    for (int i = 0; i < SIZE; ++i) link[i] = NULL;
    return;
  }
  Trie_Node *fail, *link[SIZE];
  Edge *head;
  int dfn, size;
} * node[M];
struct Edge {
  Edge() {
    p = NULL;
    nxt = NULL;
    return;
  }
  Trie_Node *p;
  Edge *nxt;
};
inline void Add_Edge(Trie_Node *u, Trie_Node *v) {
  Edge *w = new Edge();
  w->p = v;
  w->nxt = u->head;
  u->head = w;
  return;
}
bool exist[M];
char buff[LEN];
queue<Trie_Node *> que;
void BFS(Trie_Node *root) {
  root->fail = root;
  for (int i = 0; i < SIZE; ++i)
    if (root->link[i]) {
      Add_Edge(root->link[i]->fail = root, root->link[i]);
      que.push(root->link[i]);
    } else
      root->link[i] = root;
  while (!que.empty()) {
    Trie_Node *u = que.front();
    que.pop();
    for (int i = 0; i < SIZE; ++i)
      if (u->link[i]) {
        Add_Edge(u->link[i]->fail = u->fail->link[i], u->link[i]);
        que.push(u->link[i]);
      } else
        u->link[i] = u->fail->link[i];
  }
  return;
}
void DFS(Trie_Node *u) {
  u->dfn = ++dfk;
  u->size = 1;
  for (Edge *i = u->head; i; i = i->nxt) {
    Trie_Node *v = i->p;
    DFS(v);
    u->size += v->size;
  }
  return;
}
long long Query(Trie_Node *root, char *s) {
  long long res = 0;
  int j = 1, m = strlen(s + 1);
  for (Trie_Node *i = root; j <= m; ++j) {
    i = i->link[s[j] - 97];
    res += BIT::Sum(i->dfn);
  }
  return res;
}
int main() {
  scanf("%d%d", &n, &m);
  Trie_Node *root = new Trie_Node();
  for (int i = 1; i <= m; ++i) {
    scanf("%s", buff + 1);
    int k = strlen(buff + 1);
    node[i] = root;
    for (int j = 1; j <= k; node[i] = node[i]->link[buff[j] - 97], ++j)
      if (!node[i]->link[buff[j] - 97])
        node[i]->link[buff[j] - 97] = new Trie_Node();
  }
  BFS(root);
  DFS(root);
  using namespace BIT;
  for (int i = 1; i <= m; ++i) {
    Add(node[i]->dfn, 1);
    Add(node[i]->dfn + node[i]->size, -1);
  }
  memset(exist, 1, sizeof(exist));
  for (int i = 1; i <= n; ++i) {
    char t;
    cin >> t;
    if (t != '?') {
      int x;
      scanf("%d", &x);
      if (t != '-') {
        if (!exist[x]) {
          exist[x] = 1;
          Add(node[x]->dfn, 1);
          Add(node[x]->dfn + node[x]->size, -1);
        }
      } else if (exist[x]) {
        exist[x] = 0;
        Add(node[x]->dfn, -1);
        Add(node[x]->dfn + node[x]->size, 1);
      }
    } else {
      scanf("%s", buff + 1);
      printf("%lld\n", Query(root, buff));
    }
  }
  return 0;
}
