#include <bits/stdc++.h>   using namespace std;   const int maxn = 1000020;   const int maxx = 1000000;   const int MOd = 1e9 + 7;   const int K = 1000;   const int P = 143;   int loc[maxn];   class Aho_Corasick {    public:     int last, next[maxn][26];     short used[maxn][26], step;     int deg[maxn], dad[maxn];     int dep, fail[maxn];     char name[maxn];     int now[maxn], pre[maxn], E, go[maxn];     int beg[maxn], end[maxn], cnt;     int n, segment[1 << 21];     vector<int> w[maxn];     void update(int k, int x) {       for (int l = beg[k] + n - 1, r = end[k] + n - 1; l <= r;            l = (l + 1) >> 1, r = (r - 1) >> 1) {         if (l & 1) segment[l] += x;         if (~r & 1) segment[r] += x;       }     }     inline void add(int i, int j) {       pre[++E] = now[i];       now[i] = E;       go[E] = j;     }     void calc() {       for (int l = 1; l <= dep; l++) {         for (int i = now[l]; i; i = pre[i]) {           int t = fail[dad[go[i]]];           char c = name[go[i]];           while (t && used[t][c] != step) t = fail[t];           if (used[t][c] == step && next[t][c] != go[i]) t = next[t][c];           fail[go[i]] = t;           w[t].push_back(go[i]);         }       }     }     void dfs(int n) {       beg[n] = ++cnt;       for (int i = 0; i < w[n].size(); i++) dfs(w[n][i]);       end[n] = cnt;     }     inline long long find(int k) {       long long ret = 0;       for (k += n - 1; k; k >>= 1) ret += segment[k];       return ret;     }     void build(char *ar, int sz, int id) {       int p = 0;       for (int i = 1; i <= sz; i++) {         char h = ar[i] -  a ;         if (used[p][h] != step) {           used[p][h] = step;           next[p][h] = ++last;           deg[last] = deg[p] + 1;           dep = max(dep, (deg[last]));           dad[last] = p;           name[last] = h;           add(deg[last], last);         }         p = next[p][h];         if (i == sz) loc[id] = p;       }     }     long long get(char *ar, int sz) {       long long ret = 0;       int p = 0;       for (int i = 1; i <= sz; i++) {         char c = ar[i] -  a ;         while (p && used[p][c] != step) p = fail[p];         if (used[p][c] == step) p = next[p][c];         ret += find(beg[p]);       }       return ret;     }   } trie;   int len[maxn];   bool exist[maxn], used[maxn];   char ch[maxn];   int q, a;   char *ar[maxn];   int main() {     scanf( %d %d , &q, &a);     trie.n = 1 << 20;     trie.step = 1;     for (int i = 1; i <= a; i++) {       scanf(  %s , ch);       exist[i] = 1;       ar[i] = new char[strlen(ch) + 20];       memset(ar[i], 0, sizeof(ar[i]));       len[i] = strlen(ch);       for (int j = 1; j <= len[i]; j++) {         ar[i][j] = ch[j - 1];         ch[j - 1] = 0;       }       trie.build(ar[i], len[i], i);     }     trie.calc();     trie.dfs(0);     for (int i = 1; i <= a; i++) trie.update(loc[i], 1);     vector<int> w;     while (q--) {       char c;       int x;       scanf(  %c , &c);       if (c ==  ? ) {         scanf(  %s , ch + 1);         int l = strlen(ch + 1);         cout << trie.get(ch, l) << endl;       }       if (c ==  -  || c ==  + ) {         scanf( %d , &x);         if (c ==  -  && exist[x]) trie.update(loc[x], -1), exist[x] = 0;         if (c ==  +  && !exist[x]) trie.update(loc[x], 1), exist[x] = 1;       }     }     return 0;   }