#include <bits/stdc++.h>
using namespace std;
const int maxw = 1000005;
struct Trie {
  int son[26], fail, start, end;
  bool isWord;
  Trie() {
    memset(son, -1, sizeof(son));
    isWord = false;
  }
} tree[maxw];
struct Tedge {
  int v, next;
} edge[maxw * 2];
int N, Now, head[maxw], k, n, o[maxw], shead[maxw], len[maxw], tarray[maxw];
char s[1500005], st[1500005];
bool vis[maxw];
void ins(int u, int v) {
  Now++;
  edge[Now].v = v;
  edge[Now].next = head[u];
  head[u] = Now;
}
void Update(int u, int val) {
  for (; u < maxw; u += u & -u) tarray[u] += val;
}
int Take(int u) {
  int ret = 0;
  for (; u > 0; u -= u & -u) ret += tarray[u];
  return ret;
}
void Insert(char s[], int len) {
  int i, p;
  p = 1;
  for (i = 0; i < len; i++) {
    if (tree[p].son[s[i] - 'a'] == -1) {
      N++;
      tree[p].son[s[i] - 'a'] = N;
    }
    p = tree[p].son[s[i] - 'a'];
  }
  tree[p].isWord = true;
}
void edit(char s[], int len, bool th) {
  int i, p;
  p = 1;
  for (i = 0; i < len; i++) p = tree[p].son[s[i] - 'a'];
  if (tree[p].isWord == th) return;
  tree[p].isWord = th;
  if (th)
    Update(tree[p].start, 1), Update(tree[p].end + 1, -1);
  else
    Update(tree[p].start, -1), Update(tree[p].end + 1, 1);
}
void Process() {
  int h, t, i, p, Time, u;
  Trie cur;
  bool check;
  Now = -1;
  memset(head, -1, sizeof(head));
  o[0] = 1;
  tree[1].fail = 1;
  for (h = t = 0; h <= t; h++) {
    cur = tree[o[h]];
    for (i = 0; i < 26; i++)
      if (cur.son[i] != -1) {
        p = cur.fail;
        while (p != 1 && tree[p].son[i] == -1) p = tree[p].fail;
        if (o[h] == 1 || tree[p].son[i] == -1)
          tree[cur.son[i]].fail = 1;
        else
          tree[cur.son[i]].fail = tree[p].son[i];
        ins(tree[cur.son[i]].fail, cur.son[i]);
        o[++t] = cur.son[i];
      }
  }
  o[t = 1] = 1;
  Time = 0;
  while (t > 0) {
    u = o[t];
    if (!vis[u]) {
      vis[u] = true;
      Time++;
      tree[u].start = Time;
    }
    check = false;
    for (; head[u] != -1 && !check; head[u] = edge[head[u]].next) {
      o[++t] = edge[head[u]].v;
      check = true;
    }
    if (check) continue;
    tree[u].end = Time;
    if (tree[u].isWord) Update(tree[u].start, 1), Update(tree[u].end + 1, -1);
    t--;
  }
}
void AC(char s[], int len) {
  int i, p, q, ans = 0;
  p = 1;
  for (i = 0; i < len; i++) {
    while (p != 1 && tree[p].son[s[i] - 'a'] == -1) p = tree[p].fail;
    if (tree[p].son[s[i] - 'a'] != -1) p = tree[p].son[s[i] - 'a'];
    ans += Take(tree[p].start);
  }
  printf("%d\n", ans);
}
int main() {
  int i, tmp, j;
  char ch;
  N = 1;
  scanf("%d%d\n", &k, &n);
  for (i = 1; i <= n; i++) {
    scanf("%s\n", s);
    Insert(s, strlen(s));
    shead[i] = shead[i - 1] + len[i - 1];
    len[i] = strlen(s);
    for (j = shead[i]; j < shead[i] + len[i]; j++) st[j] = s[j - shead[i]];
  }
  Process();
  for (i = 1; i <= k; i++) {
    scanf("%c", &ch);
    if (ch == '+' || ch == '-') {
      scanf("%d\n", &tmp);
      edit(st + shead[tmp], len[tmp], ch == '+');
    } else {
      scanf("%s\n", s);
      AC(s, strlen(s));
    }
  }
}
