#include <bits/stdc++.h>
using namespace std;
struct SegmentTree {
  int n;
  vector<int> st;
  void init(int sz) {
    n = 1;
    while (n < sz) n <<= 1;
    st.assign(2 * n, 0);
  }
  void add(int p, int val) {
    p += n - 1;
    st[p] += val;
    for (p >>= 1; p; p >>= 1) st[p] = st[2 * p] + st[2 * p + 1];
  }
  int rangeSum(int l, int r) {
    int sum = 0;
    for (l += n - 1, r += n - 1; l <= r; l >>= 1, r >>= 1) {
      if (l & 1) sum += st[l++];
      if (!(r & 1)) sum += st[r--];
    }
    return sum;
  }
} tree;
struct Node {
  bool isEnd;
  int l, r;
  Node *nxt[26], *f, *o;
  vector<Node *> revf;
  Node() : isEnd(false), l(0), r(0), f(NULL), o(NULL) {
    for (int i = 0; i < 26; i++) nxt[i] = NULL;
  }
} * root;
int CUR_TIME = 0;
void dfs(Node *v) {
  ++CUR_TIME;
  v->l = CUR_TIME;
  for (auto c : v->revf) dfs(c);
  ++CUR_TIME;
  v->r = CUR_TIME;
}
const int MAXN = 1e5 + 50;
Node *endNode[MAXN];
vector<Node *> order;
void buildTrie(vector<string> p) {
  root = new Node();
  for (int i = 0; i < (int)p.size(); i++) {
    Node *cur = root;
    for (char c : p[i]) {
      int x = c - 'a';
      if (!cur->nxt[x]) cur->nxt[x] = new Node();
      cur = cur->nxt[x];
    }
    cur->isEnd = true;
    endNode[i] = cur;
  }
  queue<Node *> que;
  order.push_back(root);
  for (int i = 0; i < 26; i++)
    if (root->nxt[i]) {
      root->nxt[i]->f = root;
      root->revf.push_back(root->nxt[i]);
      que.push(root->nxt[i]);
    }
  while (!que.empty()) {
    Node *q = que.front();
    que.pop();
    order.push_back(q);
    if (q->isEnd)
      q->o = q;
    else
      q->o = q->f->o;
    for (int i = 0; i < 26; i++)
      if (q->nxt[i]) {
        Node *t = q->nxt[i];
        t->f = q->f;
        while (t->f != root && !t->f->nxt[i]) t->f = t->f->f;
        if (t->f->nxt[i]) t->f = t->f->nxt[i];
        t->f->revf.push_back(t);
        que.push(t);
      }
  }
  dfs(root);
  tree.init(CUR_TIME);
  for (auto t : order) {
    if (t->isEnd) {
      tree.add(t->l, 1);
      tree.add(t->r, -1);
    }
  }
}
long long query(string &s) {
  Node *cur = root;
  long long sum = 0;
  for (char c : s) {
    int x = c - 'a';
    while (cur != root && !cur->nxt[x]) cur = cur->f;
    if (cur->nxt[x]) cur = cur->nxt[x];
    sum += tree.rangeSum(1, cur->l);
  }
  return sum;
}
void update(Node *t, int val) {
  tree.add(t->l, val);
  tree.add(t->r, -val);
}
bool flag[MAXN];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int q, n;
  cin >> q >> n;
  vector<string> p(n);
  for (int i = 0; i < n; i++) cin >> p[i];
  buildTrie(p);
  for (int i = 0; i < n; i++) flag[i] = true;
  while (q--) {
    string s;
    cin >> s;
    if (s[0] == '?') {
      s = s.substr(1, s.size() - 1);
      cout << query(s) << endl;
    } else {
      int i = stoi(s.substr(1, s.size() - 1)) - 1;
      if (flag[i] != (s[0] == '-')) continue;
      update(endNode[i], (s[0] == '+') ? 1 : -1);
      flag[i] = !flag[i];
    }
  }
}
