#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void Read(T& x) {
  x = 0;
  bool flag = 0;
  char ch = getchar();
  while (ch > '9' || ch < '0') {
    if (ch == '-') {
      flag = 1;
      ch = getchar();
      break;
    }
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - 48;
    ch = getchar();
  }
  if (flag) x = -x;
}
const int MAXN = 1000010;
struct node {
  int to, next;
} E[MAXN];
int line[MAXN] = {0}, tot = 0;
inline void Insert(int x, int y) {
  tot++;
  E[tot].to = y;
  E[tot].next = line[x];
  line[x] = tot;
}
int q = 0, n = 0, cnt = 0;
int pos[MAXN] = {0};
int S[MAXN] = {0}, T[MAXN] = {0}, v[MAXN << 1] = {0};
bool used[MAXN] = {0};
struct TRIE {
  int next[MAXN][26], fail[MAXN];
  int L, root;
  int newnode() {
    for (int i = 0; i < 26; ++i) next[L][i] = -1;
    L++;
    return L - 1;
  }
  void init() {
    L = 0;
    root = newnode();
  }
  int insert(char* buf) {
    int len = strlen(buf), now = root;
    for (int i = 0; i < len; ++i) {
      if (next[now][buf[i] - 'a'] == -1) next[now][buf[i] - 'a'] = newnode();
      now = next[now][buf[i] - 'a'];
    }
    return now;
  }
  void build() {
    queue<int> Q;
    fail[root] = root;
    for (int i = 0; i < 26; ++i) {
      if (next[root][i] == -1)
        next[root][i] = root;
      else {
        fail[next[root][i]] = root;
        Q.push(next[root][i]);
      }
    }
    while (!Q.empty()) {
      int now = Q.front();
      Q.pop();
      for (int i = 0; i < 26; ++i) {
        if (next[now][i] == -1)
          next[now][i] = next[fail[now]][i];
        else {
          fail[next[now][i]] = next[fail[now]][i];
          Q.push(next[now][i]);
        }
      }
    }
  }
} AC;
inline void dfs(int x) {
  S[x] = ++tot;
  for (int i = line[x]; i > 0; i = E[i].next) dfs(E[i].to);
  T[x] = ++tot;
}
inline void change(int x, int w) {
  while (x <= 2 * (cnt + 1)) {
    v[x] += w;
    x += x & -x;
  }
}
inline int query(int x) {
  int res = 0;
  while (x > 0) {
    res += v[x];
    x -= x & -x;
  }
  return res;
}
char buf[MAXN];
int main() {
  Read(q);
  Read(n);
  AC.init();
  for (int i = 1; i <= n; ++i) {
    scanf("%s", buf);
    pos[i] = AC.insert(buf);
    used[i] = true;
  }
  AC.build();
  cnt = AC.L - 1;
  int x = 0, y = 0;
  for (int i = cnt; i >= 1; --i) {
    int x = AC.fail[i], y = i;
    Insert(x, y);
  }
  tot = 0;
  dfs(0);
  for (int i = 1; i <= n; ++i) {
    change(S[pos[i]], 1);
    change(T[pos[i]], -1);
  }
  int k = 0;
  for (int i = 1; i <= q; ++i) {
    char ch = getchar();
    while (ch != '?' && ch != '-' && ch != '+') ch = getchar();
    if (ch == '+') {
      Read(x);
      if (!used[x]) {
        used[x] = true;
        change(S[pos[x]], 1);
        change(T[pos[x]], -1);
      }
    } else {
      if (ch == '-') {
        Read(x);
        if (used[x]) {
          used[x] = false;
          change(S[pos[x]], -1);
          change(T[pos[x]], 1);
        }
      } else {
        if (ch == '?') {
          scanf("%s", buf + 1);
          x = strlen(buf + 1);
          k = AC.root;
          long long ans = 0;
          for (int i = 1; i <= x; ++i) {
            k = AC.next[k][buf[i] - 'a'];
            ans += query(S[k]);
          }
          printf("%I64d\n", ans);
        }
      }
    }
  }
  return 0;
}
