#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 50, A = 26;
int tot, son[N][26], fail[N], q[N], n;
int pos[N];
int zheng[N];
bool flag[N];
char s[N];
int start[N], endd[N];
vector<int> arr[N];
int insert(int val, char *s) {
  for (int l = strlen(s), x = 0, i = 0, w; i < l; i++) {
    if (!son[x][w = s[i] - 'a']) son[x][w] = ++tot;
    x = son[x][w];
    if (i == l - 1) {
      flag[x] = 1;
      return x;
    }
  }
}
void make() {
  int h = 1, t = 0, i, j, x;
  fail[0] = -1;
  for (i = 0; i < A; i++)
    if (son[0][i]) q[++t] = son[0][i];
  while (h <= t)
    for (x = q[h++], i = 0; i < A; i++) {
      if (flag[fail[x]]) flag[x] |= flag[fail[x]];
      if (son[x][i])
        fail[son[x][i]] = son[fail[x]][i], q[++t] = son[x][i];
      else
        son[x][i] = son[fail[x]][i];
    }
}
int cnt = 0;
int tree[N * 4];
int laz[N * 4];
void build(int root, int l, int r) {
  tree[root] = laz[root] = 0;
  if (l == r) return;
  int mid = (l + r) / 2;
  build(root * 2 + 1, l, mid);
  build(root * 2 + 2, mid + 1, r);
}
void pushdown(int root, int l, int r) {
  if (l == r || !laz[root]) return;
  laz[root * 2 + 1] += laz[root];
  laz[root * 2 + 2] += laz[root];
  tree[root * 2 + 1] += laz[root];
  tree[root * 2 + 2] += laz[root];
  laz[root] = 0;
}
void addval(int root, int l, int r, int ql, int qr, int val) {
  if (l > qr || r < ql) return;
  if (l >= ql && r <= qr) {
    tree[root] += val;
    laz[root] += val;
    return;
  }
  int mid = (l + r) / 2;
  pushdown(root, l, r);
  addval(root * 2 + 1, l, mid, ql, qr, val);
  addval(root * 2 + 2, mid + 1, r, ql, qr, val);
}
int query(int root, int l, int r, int pos) {
  if (l == r) return tree[root];
  int mid = (l + r) / 2;
  pushdown(root, l, r);
  if (pos <= mid)
    return query(root * 2 + 1, l, mid, pos);
  else
    return query(root * 2 + 2, mid + 1, r, pos);
}
bool vis[N];
void dfs(int now) {
  int i;
  start[now] = ++cnt;
  vis[now] = 1;
  for (i = 0; i < arr[now].size(); i++) dfs(arr[now][i]);
  endd[now] = cnt;
}
int finds(char *s) {
  int ans = 0;
  for (int l = strlen(s), x = 0, i = 0, w, j; i < l; i++) {
    x = son[x][w = s[i] - 'a'];
    if (flag[x]) ans += query(1, 1, cnt, start[x]);
  }
  return ans;
}
int getnum(char *s) {
  int flag = 0;
  if (s[0] == '+')
    flag = 1;
  else
    flag = -1;
  int len = strlen(s);
  int res = 0;
  for (int i = 1; i < len; i++) {
    res *= 10;
    res += s[i] - '0';
  }
  return res * flag;
}
int main() {
  int i, j;
  int Q;
  tot = cnt = 0;
  memset(son, 0, sizeof(son));
  memset(vis, 0, sizeof(vis));
  scanf("%d%d", &Q, &n);
  for (i = 1; i <= n; i++) {
    scanf("%s", s);
    pos[i] = insert(1, s);
    zheng[i] = 1;
  }
  make();
  for (i = 1; i <= tot; i++) {
    if (fail[i] > 0 && flag[i]) {
      arr[fail[i]].push_back(i);
    }
  }
  for (i = 1; i <= tot; i++)
    if (!vis[i] && flag[i]) dfs(i);
  build(1, 1, cnt);
  for (i = 1; i <= n; i++) addval(1, 1, cnt, start[pos[i]], endd[pos[i]], 1);
  while (Q--) {
    scanf("%s", s);
    if (s[0] == '?')
      printf("%d\n", finds(s + 1));
    else {
      int num = getnum(s);
      if (num < 0) {
        num *= -1;
        if (!zheng[num]) continue;
        zheng[num] = 0;
        addval(1, 1, cnt, start[pos[num]], endd[pos[num]], -1);
      } else {
        if (zheng[num]) continue;
        zheng[num] = 1;
        addval(1, 1, cnt, start[pos[num]], endd[pos[num]], 1);
      }
    }
  }
  return 0;
}
