#include <bits/stdc++.h>
using namespace std;
void SWARE(bool f) {
  if (!f)
    for (;;) puts("Welcome to Rock'n Roll Night!!");
}
const int LMAX = 1000000 + 1000000 + 100000 + 100000;
int qL, qR, qX, qA;
int N, Q;
int L;
vector<int> S, A, D, R;
int SegTree[8388608];
int nampos[100000], rangeL[100000], rangeR[100000];
bool flag[100000];
int qry[100000];
inline static int _f(int x, int n1) { return (x % 3 == 2 ? n1 : 0) + x / 3; }
inline static int _g(int x, int n1) {
  return x < n1 ? x * 3 + 1 : (x - n1) * 3 + 2;
}
inline static bool _eq(const int s[], int a, int b) {
  return s[a] == s[b] && s[a + 1] == s[b + 1] && s[a + 2] == s[b + 2];
}
static bool _le(int a, int b, const int s[], const int r[]) {
  static const int tbl[] = {2, 0, 1};
  for (int c = (a + b) % 3; s[a] == s[b]; a++, b++, c = tbl[c])
    if (!c) return r[a] < r[b];
  return s[a] < s[b];
}
static void _sort(int n, const int s[], const int x[], int y[], int z) {
  static int b[1 + LMAX];
  int i;
  for (i = 0; i <= z; i++) b[i] = 0;
  for (i = 0; i < n; i++) b[s[x[i]]]++;
  for (i = 1; i <= z; i++) b[i] += b[i - 1];
  for (i = n - 1; i >= 0; i--) y[--b[s[x[i]]]] = x[i];
}
void DC3(int N, const int S[], int A[], int Z) {
  if (N < 2) {
    if (N) A[0] = 0;
    return;
  }
  static int t[LMAX], A0[(LMAX + 2) / 3];
  const int N0 = (N + 2) / 3, N1 = (N + 1) / 3, Nr = N * 2 / 3;
  int i, j = 0, k;
  int Zr = 0, *Sr = new int[Nr + 2], *Ar = new int[Nr];
  for (i = 1; i < N; i += 3) Sr[j++] = i;
  for (i = 2; i < N; i += 3) Sr[j++] = i;
  _sort(Nr, S + 2, Sr, Ar, Z);
  _sort(Nr, S + 1, Ar, Sr, Z);
  _sort(Nr, S, Sr, Ar, Z);
  for (i = 0; i < Nr; i++)
    Sr[_f(Ar[i], N1)] = (i && _eq(S, Ar[i - 1], Ar[i]) ? Zr : ++Zr);
  if (Zr < Nr) {
    Sr[Nr + 1] = Sr[Nr] = 0;
    DC3(Nr, Sr, Ar, Zr);
  } else
    for (i = 0; i < Nr; i++) Ar[Sr[i] - 1] = i;
  j = 0;
  if (N % 3 == 1) t[j++] = N - 1;
  for (i = 0; i < Nr; i++)
    if (Ar[i] < N1) t[j++] = Ar[i] * 3;
  _sort(N0, S, t, A0, Z);
  for (i = 0; i < Nr; i++) t[Ar[i] = _g(Ar[i], N1)] = i;
  for (i = 0, j = 0, k = 0; i < N0 && j < Nr;)
    A[k++] = (_le(A0[i], Ar[j], S, t) ? A0[i++] : Ar[j++]);
  while (i < N0) A[k++] = A0[i++];
  while (j < Nr) A[k++] = Ar[j++];
  delete[] Sr;
  delete[] Ar;
}
void BLD(int N, const int S[], const int A[], const int R[], int D[]) {
  int i, j, k = 0;
  for (i = 0; i < N; i++) {
    j = (R[i] ? A[R[i] - 1] : N);
    for (k = k ? k - 1 : 0; i + k < N && j + k < N && S[i + k] == S[j + k]; k++)
      ;
    D[R[i]] = k;
  }
}
int BIT[1 + LMAX];
void add(int i, int x) {
  for (; i <= L; i += i & -i) BIT[i] += x;
}
void add(int _l, int _r, int x) {
  add(_l + 1, x);
  add(_r + 2, -x);
}
int ask(int i) {
  int ret = 0;
  if (++i > L) i = L;
  for (; i >= 1; i -= i & -i) ret += BIT[i];
  return ret;
}
bool FindL(int u, int l, int r) {
  if (SegTree[u] >= qX) return false;
  const int m = (l + r) / 2;
  if (r == l) {
    qA = m;
    return true;
  }
  if (qL <= m && FindL(u * 2, l, m)) return true;
  return qR > m && FindL(u * 2 + 1, m + 1, r);
}
bool FindR(int u, int l, int r) {
  if (SegTree[u] >= qX) return false;
  const int m = (l + r) / 2;
  if (r == l) {
    qA = m;
    return true;
  }
  if (qR > m && FindR(u * 2 + 1, m + 1, r)) return true;
  return qL <= m && FindR(u * 2, l, m);
}
int namlen(const int *p) {
  const int *q = p;
  while (*q != 1) q++;
  return q - p;
}
void solve() {
  int i, j, k;
  for (i = 1; i <= L; i++) BIT[i] = 0;
  for (i = 0; i < N; i++) {
    j = nampos[i];
    k = namlen(&S[j]);
    qL = 0;
    qR = R[j];
    qX = k;
    FindR(1, 0, L - 1);
    const int _l = qA;
    qL = R[j] + 1;
    qR = L - 1;
    qX = k;
    qA = L;
    if (qL <= qR) FindL(1, 0, L - 1);
    const int _r = qA - 1;
    rangeL[i] = _l;
    rangeR[i] = _r;
    add(_l, _r, 1);
    flag[i] = true;
  }
  for (i = 0; i < Q; i++) {
    j = qry[i] >> 2;
    k = qry[i] & 3;
    if (k == 1) {
      if (flag[j]) continue;
      add(rangeL[j], rangeR[j], 1);
      flag[j] = true;
    } else if (k == 2) {
      if (!flag[j]) continue;
      add(rangeL[j], rangeR[j], -1);
      flag[j] = false;
    } else {
      k = 0;
      while (S[j] != 2) k += ask(R[j++]);
      printf("%d\n", k);
    }
  }
}
int build(int u, int l, int r) {
  const int m = (l + r) / 2;
  if (r == l) return SegTree[u] = D[m];
  return SegTree[u] = min(build(u * 2, l, m), build(u * 2 + 1, m + 1, r));
}
void build() {
  SWARE(L <= LMAX);
  SWARE(1 <= N && N <= 100000);
  SWARE(1 <= Q && Q <= 100000);
  S.push_back(0);
  S.push_back(0);
  A.resize(L);
  D.resize(L);
  R.resize(L);
  DC3(L, &S[0], &A[0], 127);
  for (int i = 0; i < L; i++) R[A[i]] = i;
  BLD(L, &S[0], &A[0], &R[0], &D[0]);
  build(1, 0, L - 1);
}
bool input() {
  int i, j, ch;
  char c;
  if (scanf("%d%d", &Q, &N) != 2) return false;
  S.clear();
  for (i = 0; i < N; i++) {
    nampos[i] = S.size();
    scanf(" ");
    for (;;) {
      ch = getchar();
      if (!isalpha(ch)) break;
      S.push_back(ch);
    }
    S.push_back(1);
  }
  for (i = 0; i < Q; i++) {
    scanf(" %c ", &c);
    if (c == '?') {
      qry[i] = (S.size() << 2);
      for (;;) {
        ch = getchar();
        if (!isalpha(ch)) break;
        S.push_back(ch);
      }
      S.push_back(2);
    } else {
      scanf("%d", &j);
      j--;
      qry[i] = (j << 2) + (c == '+' ? 1 : 2);
    }
  }
  L = S.size();
  return true;
}
int main() {
  while (input()) {
    build();
    solve();
  }
  return 0;
}
