#include <bits/stdc++.h>
using namespace std;
int K, N, loc[1000100], visit[1000100];
struct EdgeNode {
  int next, to;
} edge[1000100 << 1];
int head[1000100], cnt = 1;
inline void AddEdge(int u, int v) {
  cnt++;
  edge[cnt].next = head[u];
  head[u] = cnt;
  edge[cnt].to = v;
}
inline void InsertEdge(int u, int v) {
  AddEdge(u, v);
  AddEdge(v, u);
}
char S[1000100];
namespace FailTree {
int son[1000100][27], end[1000100], sz = 1, fail[1000100];
inline void Insert(int x, char str[]) {
  int len = strlen(str + 1), now = 1;
  for (int i = 1; i <= len; i++)
    if (son[now][str[i] - 'a' + 1])
      now = son[now][str[i] - 'a' + 1];
    else
      son[now][str[i] - 'a' + 1] = ++sz, now = sz;
  end[now]++;
  loc[x] = now;
}
queue<int> q;
inline void Getfail() {
  q.push(1);
  while (!q.empty()) {
    int now = q.front();
    q.pop();
    for (int i = 1; i <= 26; i++)
      if (son[now][i]) {
        int fa = fail[now];
        while (fa && !son[fa][i]) fa = fail[fa];
        fail[son[now][i]] = fa ? son[fa][i] : 1;
        q.push(son[now][i]);
      }
  }
  for (int i = 1; i <= sz; i++) InsertEdge(fail[i], i);
}
}  // namespace FailTree
using namespace FailTree;
namespace Divide {
int pl[1000100], pr[1000100], dfn, tree[1000100 << 1];
inline void DFS(int now, int last) {
  pl[now] = ++dfn;
  for (int i = head[now]; i; i = edge[i].next)
    if (edge[i].to != last) DFS(edge[i].to, now);
  pr[now] = ++dfn;
}
inline int lowbit(int x) { return x & -x; }
inline void Modify(int pos, int D) {
  for (int i = pos; i <= dfn; i += lowbit(i)) tree[i] += D;
}
inline int Query(int pos) {
  int re = 0;
  for (int i = pos; i; i -= lowbit(i)) re += tree[i];
  return re;
}
inline int Calc(char str[]) {
  int len = strlen(str + 1), ans = 0, now = 1;
  for (int i = 1; i <= len; i++) {
    while (now && !son[now][str[i] - 'a' + 1]) now = fail[now];
    now = now ? son[now][str[i] - 'a' + 1] : 1;
    ans += Query(pl[now]);
  }
  return ans;
}
inline void Change(int x, int D) {
  if (visit[x] && D > 0) return;
  if (!visit[x] && D < 0) return;
  visit[x] ^= 1;
  Modify(pl[loc[x]], D);
  Modify(pr[loc[x]], -D);
}
}  // namespace Divide
using namespace Divide;
int main() {
  scanf("%d%d", &K, &N);
  for (int i = 1; i <= N; i++) scanf("%s", S + 1), Insert(i, S);
  Getfail();
  DFS(1, 0);
  for (int i = 1; i <= N; i++)
    Modify(pl[loc[i]], 1), Modify(pr[loc[i]], -1), visit[i] = 1;
  while (K--) {
    char opt = getchar();
    int x;
    while (opt != '+' && opt != '-' && opt != '?') opt = getchar();
    switch (opt) {
      case '+':
        scanf("%d", &x);
        Change(x, 1);
        break;
      case '-':
        scanf("%d", &x);
        Change(x, -1);
        break;
      case '?':
        scanf("%s", S + 1);
        printf("%d\n", Calc(S));
        break;
    }
  }
  return 0;
}
