#include <bits/stdc++.h>
using namespace std;
int q, n, nodes, idx;
vector<int> tin;
vector<int> tout;
vector<int> leaf_node;
vector<bool> status;
namespace bit {
vector<int> bit;
int sum(int r) {
  int ret = 0;
  for (; r >= 0; r = (r & (r + 1)) - 1) ret += bit[r];
  return ret;
}
void add(int idx, int delta) {
  for (; idx < nodes; idx = idx | (idx + 1)) bit[idx] += delta;
}
}  // namespace bit
namespace aho {
int go(int v, char ch);
struct trie {
  char me;
  map<int, int> down;
  vector<int> adj;
  bool is_leaf = false;
  int parent = -1;
  int link = -1;
  int exit_link = -1;
  trie(int p = -1, char ch = '$') : parent(p), me(ch) {}
};
vector<trie> ac;
int add_string(string s) {
  int v = 0;
  for (auto const &ch : s) {
    int c = ch - 'a';
    if (ac[v].down.find(c) == ac[v].down.end()) {
      ac[v].down[c] = ac.size();
      ac.emplace_back(v, ch);
    }
    v = ac[v].down[c];
  }
  ac[v].is_leaf = true;
  return v;
}
int get_link(int v) {
  if (ac[v].link == -1)
    ac[v].link =
        (!v || !ac[v].parent) ? 0 : go(get_link(ac[v].parent), ac[v].me);
  return ac[v].link;
}
int go(int v, char ch) {
  int c = ch - 'a';
  if (ac[v].down.find(c) != ac[v].down.end())
    return ac[v].down[c];
  else
    return (!v) ? 0 : go(get_link(v), ch);
}
int get_exit_link(int v) {
  if (ac[v].exit_link == -1) {
    int curr = get_link(v);
    if (!v || !curr)
      ac[v].exit_link = 0;
    else if (ac[curr].is_leaf)
      ac[v].exit_link = curr;
    else
      ac[v].exit_link = get_exit_link(curr);
  }
  return ac[v].exit_link;
}
long long int query(string s) {
  long long int ans = 0;
  int curr = 0, at;
  for (auto const &i : s) {
    curr = go(curr, i);
    ans += bit::sum(tin[curr]);
  }
  return ans;
}
void dfs(int s, int f) {
  tin[s] = idx++;
  for (auto const &v : ac[s].adj)
    if (v != f) dfs(v, s);
  tout[s] = idx++;
}
void create_tree() {
  nodes = 2 * ac.size();
  tin.resize(ac.size());
  tout.resize(ac.size());
  bit::bit.resize(nodes);
  for (int i = 1; i < ac.size(); i++) ac[get_exit_link(i)].adj.push_back(i);
  dfs(0, -1);
  for (int i = 0; i < n; i++) {
    bit::add(tin[leaf_node[i]], 1);
    bit::add(tout[leaf_node[i]], -1);
  }
}
}  // namespace aho
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> q >> n;
  status.resize(n);
  leaf_node.resize(n);
  aho::ac.resize(1);
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    leaf_node[i] = aho::add_string(s);
    status[i] = true;
  }
  aho::create_tree();
  while (q--) {
    char t;
    cin >> t;
    if (t == '+') {
      int i;
      cin >> i;
      i--;
      if (!status[i]) {
        bit::add(tin[leaf_node[i]], 1);
        bit::add(tout[leaf_node[i]], -1);
        status[i] = true;
      }
    } else if (t == '-') {
      int i;
      cin >> i;
      i--;
      if (status[i]) {
        bit::add(tin[leaf_node[i]], -1);
        bit::add(tout[leaf_node[i]], 1);
        status[i] = false;
      }
    } else {
      string s;
      cin >> s;
      cout << aho::query(s) << endl;
    }
  }
  return 0;
}
