#include <bits/stdc++.h>
using namespace std;
struct debugger {
  template <typename T>
  debugger& operator,(const T& v) {
    cerr << v << " ";
    return *this;
  }
} dbg;
int nextInt() {
  int n;
  scanf("%d", &n);
  return n;
}
void println(long long n) { printf("%lld\n", n); }
const int maxLen = (int)1e6 + 10;
const int alphabet = 26;
int st[maxLen], ed[maxLen], t = 0;
struct BIT {
  int n = maxLen;
  int dataMul[maxLen], dataAdd[maxLen];
  void init() {
    memset(dataAdd, 0, sizeof(dataAdd));
    memset(dataAdd, 0, sizeof(dataAdd));
  }
  void update(int left, int right, int by) {
    if (right <= 0) return;
    internalUpdate(left, by, -by * (left - 1));
    internalUpdate(right, -by, by * right);
  }
  void internalUpdate(int at, int mul, int add) {
    while (at < n) {
      dataMul[at] += mul;
      dataAdd[at] += add;
      at |= (at + 1);
    }
  }
  int query(int l, int r) {
    if (l == 0)
      return query(r);
    else
      return query(r) - query(l - 1);
  }
  int query(int at) {
    int mul = 0;
    int add = 0;
    int st = at;
    while (at >= 0) {
      mul += dataMul[at];
      add += dataAdd[at];
      at = (at & (at + 1)) - 1;
    }
    return mul * st + add;
  }
};
BIT bit;
vector<int> g[maxLen];
struct AhoCorasick {
  int trie[maxLen][alphabet];
  int f[maxLen];
  int idx;
  void init() {
    idx = 1;
    memset(trie[0], 0, sizeof trie[0]);
  }
  inline int get_idx(char c) { return c - 'a'; }
  int insert(char* s) {
    int u = 0;
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
      int c = get_idx(s[i]);
      if (!trie[u][c]) {
        trie[u][c] = idx++;
      }
      u = trie[u][c];
    }
    return u;
  }
  void buildFail() {
    queue<int> q;
    f[0] = 0;
    for (int c = 0; c < alphabet; ++c) {
      int u = trie[0][c];
      if (u) {
        f[u] = 0;
        q.push(u);
        g[f[u]].push_back(u);
      }
    }
    while (!q.empty()) {
      int r = q.front();
      q.pop();
      for (int c = 0; c < alphabet; ++c) {
        int u = trie[r][c];
        if (!u) continue;
        q.push(u);
        int v = f[r];
        while (v && !trie[v][c]) v = f[v];
        f[u] = trie[v][c];
        g[f[u]].push_back(u);
      }
    }
  }
  long long query(char* s) {
    long long ans = 0;
    int j = 0;
    int len = strlen(s);
    for (int i = 1; i < len; i++) {
      int c = get_idx(s[i]);
      while (j && !trie[j][c]) j = f[j];
      j = trie[j][c];
      ans += bit.query(st[j], st[j]);
    }
    return ans;
  }
};
AhoCorasick aho;
void dfs(int u) {
  st[u] = ++t;
  for (int v : g[u]) {
    dfs(v);
  }
  ed[u] = t;
}
char s[maxLen];
int id[(int)1e5 + 50];
bool vis[(int)1e5 + 50];
int main() {
  aho.init();
  bit.init();
  int q = nextInt(), n = nextInt();
  for (int i = 0; i < n; i++) {
    scanf("%s", s);
    id[i] = aho.insert(s);
    vis[i] = true;
  }
  aho.buildFail();
  dfs(0);
  for (int k = 0; k < n; k++) {
    int i = id[k];
    bit.update(st[i], ed[i], 1);
  }
  for (int i = 0; i < q; i++) {
    scanf("%s", s);
    int charLen = strlen(s);
    if (s[0] == '+') {
      int k = 0;
      for (int p = 1; p < charLen; p++) k = k * 10 + (s[p] - '0');
      k--;
      if (!vis[k]) bit.update(st[id[k]], ed[id[k]], 1);
      vis[k] = true;
    } else if (s[0] == '-') {
      int k = 0;
      for (int p = 1; p < charLen; p++) k = k * 10 + (s[p] - '0');
      k--;
      if (vis[k]) bit.update(st[id[k]], ed[id[k]], -1);
      vis[k] = false;
    } else {
      println(aho.query(s));
    }
  }
  return 0;
}
