#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
const int MAXE = 1000005;
struct Edge {
  int v, n;
  Edge() {}
  Edge(int var, int next) : v(var), n(next) {}
};
struct ac_automaton {
  int next[MAXN][26];
  int fail[MAXN];
  int word[MAXN];
  int root;
  int cur;
  int Q[MAXN];
  int head;
  int tail;
  int T[MAXN];
  int in[MAXN];
  int ou[MAXN];
  int dfs_clock;
  Edge E[MAXE];
  int H[MAXN], cntE;
  bool a[MAXN];
  inline int newnode() {
    for (int i = 0; i < 26; ++i) next[cur][i] = -1;
    return cur++;
  }
  inline void init() {
    cur = 0;
    cntE = 0;
    dfs_clock = 0;
    memset(a, 0, sizeof a);
    memset(T, 0, sizeof T);
    memset(H, -1, sizeof H);
    root = newnode();
  }
  inline void addedge(int u, int v) {
    E[cntE] = Edge(v, H[u]);
    H[u] = cntE++;
  }
  inline void insert(char buf[], int idx) {
    int now = root;
    for (int i = 0; buf[i]; ++i) {
      int x = buf[i] - 'a';
      if (next[now][x] == -1) next[now][x] = newnode();
      now = next[now][x];
    }
    word[idx] = now;
  }
  inline void build() {
    head = tail = 0;
    fail[root] = root;
    for (int i = 0; i < 26; ++i) {
      if (~next[root][i]) {
        fail[next[root][i]] = root;
        Q[tail++] = next[root][i];
      } else
        next[root][i] = root;
    }
    while (head != tail) {
      int now = Q[head++];
      for (int i = 0; i < 26; ++i) {
        if (~next[now][i]) {
          fail[next[now][i]] = next[fail[now]][i];
          Q[tail++] = next[now][i];
        } else
          next[now][i] = next[fail[now]][i];
      }
    }
    for (int i = 1; i < cur; ++i) addedge(fail[i], i);
  }
  inline void dfs(int u) {
    in[u] = ++dfs_clock;
    for (int i = H[u]; ~i; i = E[i].n) dfs(E[i].v);
    ou[u] = dfs_clock;
  }
  inline int sum(int x, int ans = 0) {
    for (int i = x; i <= dfs_clock; i += i & -i) ans += T[i];
    return ans;
  }
  inline void add(int x, int v) {
    for (int i = x; i; i -= i & -i) T[i] += v;
  }
  inline void query(char buf[]) {
    int now = root;
    long long ans = 0;
    for (int i = 0; buf[i]; ++i) {
      now = next[now][buf[i] - 'a'];
      ans += sum(in[now]);
    }
    printf("%I64d\n", ans);
  }
  inline void modify(int x, int sign) {
    int now = word[x];
    if (a[x] == 0 && sign == -1 || a[x] == 1 && sign == 1) return;
    if (a[x] == 0) {
      a[x] = 1;
      add(ou[now], 1);
      add(in[now] - 1, -1);
    } else {
      a[x] = 0;
      add(ou[now], -1);
      add(in[now] - 1, 1);
    }
  }
};
ac_automaton ac;
char buf[MAXN];
int n, k;
inline void solve() {
  char op;
  int x;
  ac.init();
  for (int i = 1; i <= k; ++i) {
    scanf("%s", buf);
    ac.insert(buf, i);
  }
  ac.build();
  ac.dfs(ac.root);
  for (int i = 1; i <= k; ++i) ac.modify(i, 1);
  while (n--) {
    scanf(" %c", &op);
    if (op == '?') {
      scanf("%s", buf);
      ac.query(buf);
    } else {
      scanf("%d", &x);
      ac.modify(x, op == '+' ? 1 : -1);
    }
  }
}
int main() {
  while (~scanf("%d%d", &n, &k)) solve();
  return 0;
}
