#include <bits/stdc++.h>
using namespace std;
int N, id[100050], flag[100050];
char st[1000050];
namespace BIT {
int a[1000050], N;
void Init(int _N) {
  memset(a, 0, sizeof(a));
  N = _N;
}
void update(int x, int v) {
  while (x <= N) {
    a[x] += v;
    x += (x & (-x));
  }
}
int ask(int x) {
  int res = 0;
  while (x) {
    res += a[x];
    x -= (x & (-x));
  }
  return res;
}
void add(int x, int y, int c) {
  update(x, +c);
  update(y + 1, -c);
}
}  // namespace BIT
namespace fail_tree {
struct Tnode {
  int id, nxt;
} edge[1000050];
int H[1000050], st[1000050], en[1000050];
int now;
void Init() {
  now = 0;
  memset(H, 0, sizeof(H));
}
void addedge(int a, int b) {
  ++now;
  edge[now].id = b;
  edge[now].nxt = H[a];
  H[a] = now;
}
int stac[1000050];
bool vis[1000050];
void dfs() {
  int top = 1, T = 0;
  stac[1] = 1;
  memset(vis, 0, sizeof(vis));
  while (top) {
    int now = stac[top];
    if (vis[now]) {
      en[now] = T;
      --top;
      continue;
    }
    vis[now] = true;
    st[now] = (++T);
    for (int tmp = H[now]; tmp; tmp = edge[tmp].nxt) stac[++top] = edge[tmp].id;
  }
}
}  // namespace fail_tree
namespace AC {
struct Tnode {
  Tnode *son[26], *fail;
  Tnode() {
    memset(son, 0, sizeof(son));
    fail = 0;
  }
} Mem[1000050], *now, *root;
Tnode *NewNode() { return (++now); }
void Init() {
  now = Mem;
  root = NewNode();
}
void Insert(char *st, int &id) {
  Tnode *it = root;
  while ((*st)) {
    int w = (*st) - 'a';
    if (!(it->son[w])) it->son[w] = NewNode();
    it = it->son[w];
    ++st;
  }
  id = (it - Mem);
}
Tnode *q[1000050];
void Build() {
  fail_tree ::Init();
  int head = 1, tail = 0;
  root->fail = root;
  for (int i = 0; i < 26; ++i)
    if (root->son[i]) {
      root->son[i]->fail = root;
      q[++tail] = root->son[i];
    }
  while (head <= tail) {
    Tnode *now = q[head++];
    for (int i = 0; i < 26; ++i)
      if (now->son[i]) {
        Tnode *nxt = now->son[i];
        Tnode *tmp = now->fail;
        while (tmp != root && !(tmp->son[i])) tmp = tmp->fail;
        if (tmp->son[i])
          nxt->fail = tmp->son[i];
        else
          nxt->fail = root;
        q[++tail] = now->son[i];
      }
  }
  for (Tnode *it = Mem + 1; it <= now; ++it)
    fail_tree ::addedge((it->fail) - Mem, it - Mem);
  fail_tree ::dfs();
  BIT ::Init(now - Mem);
}
int Match(char *st) {
  Tnode *now = root;
  long long res = 0;
  while (*st) {
    int w = (*st) - 'a';
    while (now != root && !(now->son[w])) now = now->fail;
    if (now->son[w]) {
      now = now->son[w];
      res += (BIT ::ask(fail_tree::st[now - Mem]));
    }
    ++st;
  }
  return res;
}
}  // namespace AC
int main() {
  int Q;
  scanf("%d%d", &Q, &N);
  AC ::Init();
  for (int i = 1; i <= N; ++i) {
    scanf("%s", st);
    AC ::Insert(st, id[i]);
  }
  AC ::Build();
  for (int i = 1; i <= N; ++i) {
    flag[i] = 1;
    BIT ::add(fail_tree::st[id[i]], fail_tree::en[id[i]], +1);
  }
  while (Q--) {
    scanf("%s", st);
    if (st[0] == '?')
      printf("%d\n", AC ::Match(st + 1));
    else {
      int t;
      sscanf(st + 1, "%d", &t);
      if (st[0] == '+' && flag[t] == 0) {
        flag[t] = 1;
        BIT ::add(fail_tree::st[id[t]], fail_tree::en[id[t]], +1);
      }
      if (st[0] == '-' && flag[t] == 1) {
        flag[t] = 0;
        BIT ::add(fail_tree::st[id[t]], fail_tree::en[id[t]], -1);
      }
    }
  }
  return 0;
}
