#include <bits/stdc++.h>   using namespace std;   const int N = 100010, M = 100010, SIZE = 26, LEN = 1000010;   int n, m, dfk = 0;   namespace BIT {   int c[LEN];   void Add(int x, int k) {     for (; x <= dfk; x += x & -x) c[x] += k;     return;   }   int Sum(int x) {     int sum = 0;     for (; x; x -= x & -x) sum += c[x];     return sum;   }   }  // namespace BIT   struct Trie_Node;   struct Edge;   struct Trie_Node {     Trie_Node() {       dfn = size = 0;       head = NULL;       fail = NULL;       for (int i = 0; i < SIZE; ++i) link[i] = NULL;       return;     }     Trie_Node *fail, *link[SIZE];     Edge *head;     int dfn, size;   } * node[M];   struct Edge {     Edge() {       p = NULL;       nxt = NULL;       return;     }     Trie_Node *p;     Edge *nxt;   };   inline void Add_Edge(Trie_Node *u, Trie_Node *v) {     Edge *w = new Edge();     w->p = v;     w->nxt = u->head;     u->head = w;     return;   }   bool exist[M];   char buff[LEN];   queue<Trie_Node *> que;   void BFS(Trie_Node *root) {     root->fail = root;     for (int i = 0; i < SIZE; ++i)       if (root->link[i]) {         Add_Edge(root->link[i]->fail = root, root->link[i]);         que.push(root->link[i]);       } else         root->link[i] = root;     while (!que.empty()) {       Trie_Node *u = que.front();       que.pop();       for (int i = 0; i < SIZE; ++i)         if (u->link[i]) {           Add_Edge(u->link[i]->fail = u->fail->link[i], u->link[i]);           que.push(u->link[i]);         } else           u->link[i] = u->fail->link[i];     }     return;   }   void DFS(Trie_Node *u) {     u->dfn = ++dfk;     u->size = 1;     for (Edge *i = u->head; i; i = i->nxt) {       Trie_Node *v = i->p;       DFS(v);       u->size += v->size;     }     return;   }   long long Query(Trie_Node *root, char *s) {     long long res = 0;     int j = 1, m = strlen(s + 1);     for (Trie_Node *i = root; j <= m; ++j) {       i = i->link[s[j] - 97];       res += BIT::Sum(i->dfn);     }     return res;   }   int main() {     scanf( %d%d , &n, &m);     Trie_Node *root = new Trie_Node();     for (int i = 1; i <= m; ++i) {       scanf( %s , buff + 1);       int k = strlen(buff + 1);       node[i] = root;       for (int j = 1; j <= k; node[i] = node[i]->link[buff[j] - 97], ++j)         if (!node[i]->link[buff[j] - 97])           node[i]->link[buff[j] - 97] = new Trie_Node();     }     BFS(root);     DFS(root);     using namespace BIT;     for (int i = 1; i <= m; ++i) {       Add(node[i]->dfn, 1);       Add(node[i]->dfn + node[i]->size, -1);     }     memset(exist, 1, sizeof(exist));     for (int i = 1; i <= n; ++i) {       char t;       cin >> t;       if (t !=  ? ) {         int x;         scanf( %d , &x);         if (t !=  - ) {           if (!exist[x]) {             exist[x] = 1;             Add(node[x]->dfn, 1);             Add(node[x]->dfn + node[x]->size, -1);           }         } else if (exist[x]) {           exist[x] = 0;           Add(node[x]->dfn, -1);           Add(node[x]->dfn + node[x]->size, 1);         }       } else {         scanf( %s , buff + 1);         printf( %lld n , Query(root, buff));       }     }     return 0;   }   