#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 500;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ll _hash = gethash(s);
      ht[_hash] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[_hash] = m;
      else
        ban[idx[_hash]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first] || all[i].second.size() > s.size())continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz];
//          while(j > 0 && f[j] != s[k])
//            j = pf[j - 1];
//          if(f[j] == s[k])
//            ++ j;
//          pf[k] = j;
//          if(pf[k] >= sz)
//            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 15000;

ll P[N];
bool ban[N];

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

unordered_map<ll, int, custom_hash> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = all[i].second.size();
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j
        }
//        for(int k = 0; k < s.size(); k ++){
//          int j = pf[f.size()];
//          while(j > 0 && f[j] != s[k])
//            j = pf[j - 1];
//          if(f[j] == s[k])
//            ++ j;
//          pf[k] = j;
//          if(pf[k] >= sz)
//            res ++;
//        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20000;

ll P[N];
bool ban[N];
unordered_map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const int N = 3e5 + 200;
const int W = 7000;

int go[N][26], p[N], g, cnt = 1, value[N], cost[N];
string longs[N];

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  int q; cin >> q;
  while(q --){
    int t;
    string s;
    cin >> t >> s;
    int n = s.size();
    if(t == 1 || t == 2){
      if(n <= W){
        int a = 1;
        for(int i = 0; i < n; i ++){
          int c = s[i] - 'a';
          if(go[a][c] == 0)
            go[a][c] = ++cnt;
          a = go[a][c];
        }
        value[a] += (3 - 2 * t);
      }else{
        longs[g] = s + "#";
        cost[g] = 3 - 2 * t;
        g ++;
      }
    }else{
      ll ans = 0;
      for(int i = 0; i < n; i ++){
        int a = 1;
        for(int j = i; j < n; j ++){
          int c = s[j] - 'a';
          if(go[a][c] == 0)
            break;
          a = go[a][c];
          ans += value[a];
        }
      }
      for(int i = 0; i < g; i ++){
        int m = longs[i].size(); m --;
        if(m > n)
          continue;
        int j = 0;
        for(int k = 1; k <= m; k ++){
          while(j > 0 && longs[i][j] != longs[i][k])
            j = p[j - 1];
          if(longs[i][j] == longs[i][k])
            ++ j;
          p[k] = j;
        }
        j = 0;
        for(int k = 0; k < n; k ++){
          while(j > 0 && s[k] != longs[i][j])
            j = p[j - 1];
          if(s[k] == longs[i][j])
            ++ j;
          if(j == m)
            ans += cost[i];
        }
      }
      cout << ans << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 500;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = all[i].second.size();
        string f = all[i].second + "#" + s;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
          if(pf[k] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[m] = true;
      if(t == 1)
        all.push_back({m, s});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = all[i].second.size();
        string f = all[i].second + "#" + s;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
//          if(pf[k] == sz)
//            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 500;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ll _hash = gethash(s);
      ht[_hash] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[_hash] = m;
      else
        ban[idx[_hash]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first] || all[i].second > s.size())continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#pragma GCC diagnostic error "-std=c++11"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 1300;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 10000;

ll P[N];
bool ban[N];

unordered_map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ll _hash = gethash(s);
      ht[_hash] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[_hash] = m;
      else
        ban[idx[_hash]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 1300;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ll _hash = gethash(s);
      ht[_hash] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[_hash] = m;
      else
        ban[idx[_hash]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = all[i].second.size();
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
          if(pf[k] >= sz)
            res ++;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[f.size()];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k] = j;
          if(pf[k] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 20;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k] = j;
          if(pf[k] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 500;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[m] = true;
      if(t == 1)
        all.push_back({m, s});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        string& f = all[i].second;
        int sz = f.size();
        f += "#";
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[f.size()];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[f.size() + k] = j;
          if(pf[f.size() + k] >= sz)
            res ++;
        }
        f.pop_back();
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 500;

ll P[N];
bool ban[N];
map<ll, int> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ht[gethash(s)] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[gethash(s)] = m;
      else
        ban[idx[gethash(s)]] = true;
      if(t == 1)
        all.push_back({m, s});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= W; lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        string& f = all[i].second;
        int sz = f.size();
        f += "#";
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[f.size()];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[f.size() + k] = j;
          if(pf[f.size() + k] >= sz)
            res ++;
        }
        f.pop_back();
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const int N = 3e5 + 200;
const int W = 500;

int go[N][26], p[N], g, cnt = 1, value[N], cost[N];
string longs[N];

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  int q; cin >> q;
  while(q --){
    int t;
    string s;
    cin >> t >> s;
    int n = s.size();
    if(t == 1 || t == 2){
      if(n <= W){
        int a = 1;
        for(int i = 0; i < n; i ++){
          int c = s[i] - 'a';
          if(go[a][c] == 0)
            go[a][c] = ++cnt;
          a = go[a][c];
        }
        value[a] += (3 - 2 * t);
      }else{
        longs[g] = s + "#";
        cost[g] = 3 - 2 * t;
        g ++;
      }
    }else{
      ll ans = 0;
      for(int i = 0; i < n; i ++){
        int a = 1;
        for(int j = i; j < n; j ++){
          int c = s[j] - 'a';
          if(go[a][c] == 0)
            break;
          a = go[a][c];
          ans += value[a];
        }
      }
      for(int i = 0; i < g; i ++){
        int m = longs[i].size(); m --;
        if(m > n)
          continue;
        int j = 0;
        for(int k = 1; k <= m; k ++){
          while(j > 0 && longs[i][j] != longs[i][k])
            j = p[j - 1];
          if(longs[i][j] == longs[i][k])
            ++ j;
          p[k] = j;
        }
        j = 0;
        for(int k = 0; k < n; k ++){
          while(j > 0 && s[k] != longs[i][j])
            j = p[j - 1];
          if(s[k] == longs[i][j])
            ++ j;
          if(j == m)
            ans += cost[i];
        }
      }
      cout << ans << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const int N = 3e5 + 200;
const int W = 1500;

int go[N][26], p[N], g, cnt = 1, value[N], cost[N];
string longs[N];

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  int q; cin >> q;
  while(q --){
    int t;
    string s;
    cin >> t >> s;
    int n = s.size();
    if(t == 1 || t == 2){
      if(n <= W){
        int a = 1;
        for(int i = 0; i < n; i ++){
          int c = s[i] - 'a';
          if(go[a][c] == 0)
            go[a][c] = ++cnt;
          a = go[a][c];
        }
        value[a] += (3 - 2 * t);
      }else{
        longs[g] = s + "#";
        cost[g] = 3 - 2 * t;
        g ++;
      }
    }else{
      ll ans = 0;
      for(int i = 0; i < n; i ++){
        int a = 1;
        for(int j = i; j < n; j ++){
          int c = s[j] - 'a';
          if(go[a][c] == 0)
            break;
          a = go[a][c];
          ans += value[a];
        }
      }
      for(int i = 0; i < g; i ++){
        int m = longs[i].size(); m --;
        if(m > n)
          continue;
        int j = 0;
        for(int k = 1; k <= m; k ++){
          while(j > 0 && longs[i][j] != longs[i][k])
            j = p[j - 1];
          if(longs[i][j] == longs[i][k])
            ++ j;
          p[k] = j;
        }
        j = 0;
        for(int k = 0; k < n; k ++){
          while(j > 0 && s[k] != longs[i][j])
            j = p[j - 1];
          if(s[k] == longs[i][j])
            ++ j;
          if(j == m)
            ans += cost[i];
        }
      }
      cout << ans << endl;
    }
  }
}


#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const ll p = 31;

const int N = 4e5 + 200;
const int W = 10000;

ll P[N];
bool ban[N];

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

unordered_map<ll, int, custom_hash> ht, idx;
vector<pair<int, string>> all;
int pf[N];

ll gethash(const string& s){
  ll h = 0;
  for(int j = 0; j < s.size(); j ++){
    h = (h * p + (s[j] - 'a' + 1)) % mod;
  }
  return h;
}

int main(){
#ifdef LOCAL
//  freopen("test.txt", "r", stdin);
#endif
//  ios_base::sync_with_stdio(0);
//  cin.tie(0); cout.tie(0);
  P[0] = 1;
  for(int i = 1; i < N; i ++)
    P[i] = P[i - 1] * p % mod;
  int m; cin >> m;
  while(m --){
    int t;
    string s;
    cin >> t >> s;
    if(t == 1 || t == 2){
      ll _hash = gethash(s);
      ht[_hash] += (t == 1 ? 1 : -1);
      if(t == 1)
        idx[_hash] = m;
      else
        ban[idx[_hash]] = true;
      if(t == 1)
        all.push_back({m, s + "#"});
    }else if(s.size() <= W){
      int res = 0;
      for(int lng = 1; lng <= min((int)s.size(), W); lng ++){
        ll h = 0;
        for(int j = 0; j < s.size(); j ++){
          h = (h * p + (s[j] - 'a' + 1)) % mod;
          if(j >= lng){
            h -= (s[j - lng] - 'a' + 1) * P[lng] % mod;
            h = (h + mod) % mod;
          }
          if(j + 1 >= lng){
            res += ht[h];
          }
        }
      }
      cout << res << endl;
    }else{
      int res = 0;
      for(int i = 0; i < all.size(); i ++){
        if(ban[all[i].first]) continue;
        int sz = (int)all[i].second.size() - 1;
        string& f = all[i].second;
        for(int k = 1; k < f.size(); k ++){
          int j = pf[k - 1];
          while(j > 0 && f[j] != f[k])
            j = pf[j - 1];
          if(f[j] == f[k])
            ++ j;
          pf[k] = j;
        }
        for(int k = 0; k < s.size(); k ++){
          int j = pf[sz + k];
          while(j > 0 && f[j] != s[k])
            j = pf[j - 1];
          if(f[j] == s[k])
            ++ j;
          pf[k + sz + 1] = j;
          if(pf[k + sz + 1] >= sz)
            res ++;
        }
      }
      cout << res << endl;
    }
  }
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const ll MOD = 1'000'000'000'000'037;

// custom hash table
struct htable {
	vector<ll> content, table;
	int mask;

	htable() : table(8, -1), mask(3) {}

	void expand() {
		table = vector<ll>(table.size() * 4, -1);
		mask = 4*mask + 3;
		for (ll x : content)
			add_impl(x);
	}

	void add_impl(ll x) {
		int p = x & mask;
		while (table[p] != -1)
			p++;
		table[p] = x;
	}

	void add(ll x) {
		if (content.size() * 4 == table.size())
			expand();
		add_impl(x);
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & mask;
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p++;
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

ll p[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p[0] = 1;
	for (int i=1; i<300005; i++)
		p[i] = p[i-1] * 127 % MOD;

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {
			if (s.size() > 150000)
				continue; // cool
			ll h = 0;
			for (char x : s)
				h = (h * 127 + x) % MOD;
			auto gde = t == 1 ? dodato : obrisano;
			gde[s.size()].add(h);
			dodaj_velicinu(s.size());
		} else {
			int ans = 0;
			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				ll h = 0;
				for (int i=0; i<vel; i++)
					h = (h * 127 + s[i]) % MOD;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(h) - obrisano[vel].count(h);
					// pomeri
					if (i == (int)s.size())
						break;
					h = h * 127 + s[i] - p[vel] * s[i-vel];
					h %= MOD;
					if (h < 0)
						h += MOD;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#include <bits/stdc++.h>
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

template<int m>
struct modint {

	unsigned x;

	modint() : x(0) {}

	modint(long long arg) {
		arg %= m;
		if (arg < 0) {
			x = arg + m;
		} else {
			x = arg;
		}
	}

	modint& operator+= (const modint& other) {
		x += other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint& operator*= (const modint& other) {
		x = (x * 1ll * other.x) % m;
		return *this;
	}

	modint& operator-= (const modint& other) {
		x += m - other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint operator+ (const modint& other) const {
		modint tmp = *this;
		tmp += other;
		return tmp;
	}

	modint operator- (const modint& other) const {
		modint tmp = *this;
		tmp -= other;
		return tmp;
	}

	modint operator* (const modint& other) const {
		modint tmp = *this;
		tmp *= other;
		return tmp;
	}

	explicit operator int () const {
		return x;
	}

	modint& operator++ () {
		++x;
		if (x == m) {
			x = 0;
		}
		return *this;
	}

	modint& operator-- () {
		if (x == 0) {
			x = m-1;
		} else {
			--x;
		}
		return *this;
	}

	modint operator++ (int) {
		modint tmp = *this;
		++*this;
		return tmp;
	}

	modint operator-- (int) {
		modint tmp = *this;
		--*this;
		return tmp;
	}

	bool operator== (const modint& other) const {
		return x == other.x;
	}

	bool operator!= (const modint& other) const {
		return x != other.x;
	}

	template<class T>
	modint operator^ (T arg) const {
		if (arg == 0) {
			return 1;
		}
		if (arg == 1) {
			return x;
		}
		auto t = *this ^ (arg >> 1);
		t *= t;
		if (arg & 1) {
			t *= *this;
		}
		return t;
	}

	modint inv() const {
		return *this ^ (m-2);
	}
};

typedef modint<1000000007> mint1;
typedef modint<1000000009> mint2;

// custom hash table
struct htable {
	vector<ll> content, table;

	htable() : table(4, -1) {}

	void expand() {
		table = vector<ll>(table.size() * 2, -1);
		for (ll x : content)
			add(x);
	}

	void add(ll x) {
		if (content.size() * 2 == table.size())
			expand();
		int p = x & (table.size() - 1);
		while (table[p] != -1)
			p = (p+1) & (table.size() - 1);
		table[p] = x;
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & (table.size() - 1);
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p = (p+1) & (table.size() - 1);
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

mint1 p1[300005];
mint2 p2[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p1[0] = 1;
	p2[0] = 1;

	for (int i=1; i<300005; i++) {
		p1[i] = p1[i-1] * 127;
		p2[i] = p2[i-1] * 129;
	}

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {

			if (s.size() > 150000)
				continue; // cool

			mint1 h1;
			mint2 h2;

			for (char x : s) {
				h1 = h1 * 127 + x;
				h2 = h2 * 129 + x;
			}

			auto gde = t == 1 ? dodato : obrisano;
			ll hv = (int)h1 * 1123123123ll + (int)h2;
			gde[s.size()].add(hv);
			dodaj_velicinu(s.size());
		} else {

			int ans = 0;

			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				mint1 h1;
				mint2 h2;
				for (int i=0; i<vel; i++) {
					h1 = h1 * 127 + s[i];
					h2 = h2 * 129 + s[i];
				}

				ll hv = (int)h1 * 1123123123ll + (int)h2;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(hv) - obrisano[vel].count(hv);
					// pomeri
					if (i == (int)s.size())
						break;
					h1 = h1 * 127 + s[i] - p1[vel] * s[i-vel];
					h2 = h2 * 129 + s[i] - p2[vel] * s[i-vel];
					hv = (int)h1 * 1123123123ll + (int)h2;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

template<int m>
struct modint {

	unsigned x;

	modint() : x(0) {}

	modint(long long arg) {
		arg %= m;
		if (arg < 0) {
			x = arg + m;
		} else {
			x = arg;
		}
	}

	modint& operator+= (const modint& other) {
		x += other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint& operator*= (const modint& other) {
		x = (x * 1ll * other.x) % m;
		return *this;
	}

	modint& operator-= (const modint& other) {
		x += m - other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint operator+ (const modint& other) const {
		modint tmp = *this;
		tmp += other;
		return tmp;
	}

	modint operator- (const modint& other) const {
		modint tmp = *this;
		tmp -= other;
		return tmp;
	}

	modint operator* (const modint& other) const {
		modint tmp = *this;
		tmp *= other;
		return tmp;
	}

	explicit operator int () const {
		return x;
	}

	modint& operator++ () {
		++x;
		if (x == m) {
			x = 0;
		}
		return *this;
	}

	modint& operator-- () {
		if (x == 0) {
			x = m-1;
		} else {
			--x;
		}
		return *this;
	}

	modint operator++ (int) {
		modint tmp = *this;
		++*this;
		return tmp;
	}

	modint operator-- (int) {
		modint tmp = *this;
		--*this;
		return tmp;
	}

	bool operator== (const modint& other) const {
		return x == other.x;
	}

	bool operator!= (const modint& other) const {
		return x != other.x;
	}

	template<class T>
	modint operator^ (T arg) const {
		if (arg == 0) {
			return 1;
		}
		if (arg == 1) {
			return x;
		}
		auto t = *this ^ (arg >> 1);
		t *= t;
		if (arg & 1) {
			t *= *this;
		}
		return t;
	}

	modint inv() const {
		return *this ^ (m-2);
	}
};

typedef modint<1000000007> mint1;
typedef modint<1000000009> mint2;

// custom hash table
struct htable {
	vector<ll> content, table;
	int mask;

	htable() : table(8, -1), mask(3) {}

	void expand() {
		table = vector<ll>(table.size() * 4, -1);
		mask = 4*mask + 3;
		for (ll x : content)
			add_impl(x);
	}

	void add_impl(ll x) {
		int p = x & mask;
		while (table[p] != -1)
			p++;
		table[p] = x;
	}

	void add(ll x) {
		if (content.size() * 4 == table.size())
			expand();
		add_impl(x);
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & mask;
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p++;
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

mint1 p1[300005];
mint2 p2[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p1[0] = 1;
	p2[0] = 1;

	for (int i=1; i<300005; i++) {
		p1[i] = p1[i-1] * 127;
		p2[i] = p2[i-1] * 129;
	}

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {

			if (s.size() > 150000)
				continue; // cool

			mint1 h1;
			mint2 h2;

			for (char x : s) {
				h1 = h1 * 127 + x;
				h2 = h2 * 129 + x;
			}

			auto gde = t == 1 ? dodato : obrisano;
			ll hv = (int)h1 * 1123123123ll + (int)h2;
			gde[s.size()].add(hv);
			dodaj_velicinu(s.size());
		} else {

			int ans = 0;

			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				mint1 h1;
				mint2 h2;
				for (int i=0; i<vel; i++) {
					h1 = h1 * 127 + s[i];
					h2 = h2 * 129 + s[i];
				}

				ll hv = (int)h1 * 1123123123ll + (int)h2;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(hv) - obrisano[vel].count(hv);
					// pomeri
					if (i == (int)s.size())
						break;
					h1 = h1 * 127 + s[i] - p1[vel] * s[i-vel];
					h2 = h2 * 129 + s[i] - p2[vel] * s[i-vel];
					hv = (int)h1 * 1123123123ll + (int)h2;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

template<int m>
struct modint {

	unsigned x;

	modint() : x(0) {}

	modint(long long arg) {
		arg %= m;
		if (arg < 0) {
			x = arg + m;
		} else {
			x = arg;
		}
	}

	modint& operator+= (const modint& other) {
		x += other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint& operator*= (const modint& other) {
		x = (x * 1ll * other.x) % m;
		return *this;
	}

	modint& operator-= (const modint& other) {
		x += m - other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint operator+ (const modint& other) const {
		modint tmp = *this;
		tmp += other;
		return tmp;
	}

	modint operator- (const modint& other) const {
		modint tmp = *this;
		tmp -= other;
		return tmp;
	}

	modint operator* (const modint& other) const {
		modint tmp = *this;
		tmp *= other;
		return tmp;
	}

	explicit operator int () const {
		return x;
	}

	modint& operator++ () {
		++x;
		if (x == m) {
			x = 0;
		}
		return *this;
	}

	modint& operator-- () {
		if (x == 0) {
			x = m-1;
		} else {
			--x;
		}
		return *this;
	}

	modint operator++ (int) {
		modint tmp = *this;
		++*this;
		return tmp;
	}

	modint operator-- (int) {
		modint tmp = *this;
		--*this;
		return tmp;
	}

	bool operator== (const modint& other) const {
		return x == other.x;
	}

	bool operator!= (const modint& other) const {
		return x != other.x;
	}

	template<class T>
	modint operator^ (T arg) const {
		if (arg == 0) {
			return 1;
		}
		if (arg == 1) {
			return x;
		}
		auto t = *this ^ (arg >> 1);
		t *= t;
		if (arg & 1) {
			t *= *this;
		}
		return t;
	}

	modint inv() const {
		return *this ^ (m-2);
	}
};

typedef modint<1000000007> mint1;
typedef modint<1000000009> mint2;

// custom hash table
struct htable {
	vector<ll> content, table;

	htable() : table(4, -1) {}

	void expand() {
		table = vector<ll>(table.size() * 4, -1);
		for (ll x : content)
			add(x);
	}

	void add(ll x) {
		if (content.size() * 4 == table.size())
			expand();
		int p = x & (table.size() - 1);
		while (table[p] != -1)
			p = (p+1) & (table.size() - 1);
		table[p] = x;
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & (table.size() - 1);
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p = (p+1) & (table.size() - 1);
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

mint1 p1[300005];
mint2 p2[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p1[0] = 1;
	p2[0] = 1;

	for (int i=1; i<300005; i++) {
		p1[i] = p1[i-1] * 127;
		p2[i] = p2[i-1] * 129;
	}

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {

			if (s.size() > 150000)
				continue; // cool

			mint1 h1;
			mint2 h2;

			for (char x : s) {
				h1 = h1 * 127 + x;
				h2 = h2 * 129 + x;
			}

			auto gde = t == 1 ? dodato : obrisano;
			ll hv = (int)h1 * 1123123123ll + (int)h2;
			gde[s.size()].add(hv);
			dodaj_velicinu(s.size());
		} else {

			int ans = 0;

			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				mint1 h1;
				mint2 h2;
				for (int i=0; i<vel; i++) {
					h1 = h1 * 127 + s[i];
					h2 = h2 * 129 + s[i];
				}

				ll hv = (int)h1 * 1123123123ll + (int)h2;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(hv) - obrisano[vel].count(hv);
					// pomeri
					if (i == (int)s.size())
						break;
					h1 = h1 * 127 + s[i] - p1[vel] * s[i-vel];
					h2 = h2 * 129 + s[i] - p2[vel] * s[i-vel];
					hv = (int)h1 * 1123123123ll + (int)h2;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

template<int m>
struct modint {

	unsigned x;

	modint() : x(0) {}

	modint(long long arg) {
		arg %= m;
		if (arg < 0) {
			x = arg + m;
		} else {
			x = arg;
		}
	}

	modint& operator+= (const modint& other) {
		x += other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint& operator*= (const modint& other) {
		x = (x * 1ll * other.x) % m;
		return *this;
	}

	modint& operator-= (const modint& other) {
		x += m - other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint operator+ (const modint& other) const {
		modint tmp = *this;
		tmp += other;
		return tmp;
	}

	modint operator- (const modint& other) const {
		modint tmp = *this;
		tmp -= other;
		return tmp;
	}

	modint operator* (const modint& other) const {
		modint tmp = *this;
		tmp *= other;
		return tmp;
	}

	explicit operator int () const {
		return x;
	}

	modint& operator++ () {
		++x;
		if (x == m) {
			x = 0;
		}
		return *this;
	}

	modint& operator-- () {
		if (x == 0) {
			x = m-1;
		} else {
			--x;
		}
		return *this;
	}

	modint operator++ (int) {
		modint tmp = *this;
		++*this;
		return tmp;
	}

	modint operator-- (int) {
		modint tmp = *this;
		--*this;
		return tmp;
	}

	bool operator== (const modint& other) const {
		return x == other.x;
	}

	bool operator!= (const modint& other) const {
		return x != other.x;
	}

	template<class T>
	modint operator^ (T arg) const {
		if (arg == 0) {
			return 1;
		}
		if (arg == 1) {
			return x;
		}
		auto t = *this ^ (arg >> 1);
		t *= t;
		if (arg & 1) {
			t *= *this;
		}
		return t;
	}

	modint inv() const {
		return *this ^ (m-2);
	}
};

typedef modint<1000000007> mint1;
typedef modint<1000000009> mint2;

// custom hash table
struct htable {
	vector<ll> content, table;

	htable() : table(4, -1) {}

	void expand() {
		table = vector<ll>(table.size() * 2, -1);
		for (ll x : content)
			add(x);
	}

	void add(ll x) {
		if (content.size() * 2 == table.size())
			expand();
		int p = x & (table.size() - 1);
		while (table[p] != -1)
			p = (p+1) & (table.size() - 1);
		table[p] = x;
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & (table.size() - 1);
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p = (p+1) & (table.size() - 1);
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

mint1 p1[300005];
mint2 p2[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p1[0] = 1;
	p2[0] = 1;

	for (int i=1; i<300005; i++) {
		p1[i] = p1[i-1] * 127;
		p2[i] = p2[i-1] * 129;
	}

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {

			if (s.size() > 150000)
				continue; // cool

			mint1 h1;
			mint2 h2;

			for (char x : s) {
				h1 = h1 * 127 + x;
				h2 = h2 * 129 + x;
			}

			auto gde = t == 1 ? dodato : obrisano;
			ll hv = (int)h1 * 1123123123ll + (int)h2;
			gde[s.size()].add(hv);
			dodaj_velicinu(s.size());
		} else {

			int ans = 0;

			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				mint1 h1;
				mint2 h2;
				for (int i=0; i<vel; i++) {
					h1 = h1 * 127 + s[i];
					h2 = h2 * 129 + s[i];
				}

				ll hv = (int)h1 * 1123123123ll + (int)h2;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(hv) - obrisano[vel].count(hv);
					// pomeri
					if (i == (int)s.size())
						break;
					h1 = h1 * 127 + s[i] - p1[vel] * s[i-vel];
					h2 = h2 * 129 + s[i] - p2[vel] * s[i-vel];
					hv = (int)h1 * 1123123123ll + (int)h2;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

template<int m>
struct modint {

	unsigned x;

	modint() : x(0) {}

	modint(long long arg) {
		arg %= m;
		if (arg < 0) {
			x = arg + m;
		} else {
			x = arg;
		}
	}

	modint& operator+= (const modint& other) {
		x += other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint& operator*= (const modint& other) {
		x = (x * 1ll * other.x) % m;
		return *this;
	}

	modint& operator-= (const modint& other) {
		x += m - other.x;
		if (x >= m) {
			x -= m;
		}
		return *this;
	}

	modint operator+ (const modint& other) const {
		modint tmp = *this;
		tmp += other;
		return tmp;
	}

	modint operator- (const modint& other) const {
		modint tmp = *this;
		tmp -= other;
		return tmp;
	}

	modint operator* (const modint& other) const {
		modint tmp = *this;
		tmp *= other;
		return tmp;
	}

	explicit operator int () const {
		return x;
	}

	modint& operator++ () {
		++x;
		if (x == m) {
			x = 0;
		}
		return *this;
	}

	modint& operator-- () {
		if (x == 0) {
			x = m-1;
		} else {
			--x;
		}
		return *this;
	}

	modint operator++ (int) {
		modint tmp = *this;
		++*this;
		return tmp;
	}

	modint operator-- (int) {
		modint tmp = *this;
		--*this;
		return tmp;
	}

	bool operator== (const modint& other) const {
		return x == other.x;
	}

	bool operator!= (const modint& other) const {
		return x != other.x;
	}

	template<class T>
	modint operator^ (T arg) const {
		if (arg == 0) {
			return 1;
		}
		if (arg == 1) {
			return x;
		}
		auto t = *this ^ (arg >> 1);
		t *= t;
		if (arg & 1) {
			t *= *this;
		}
		return t;
	}

	modint inv() const {
		return *this ^ (m-2);
	}
};

typedef modint<1000000007> mint1;
typedef modint<1000000009> mint2;

// custom hash table
struct htable {
	vector<ll> content, table;

	htable() : table(4, -1) {}

	void expand() {
		table = vector<ll>(table.size() * 4, -1);
		for (ll x : content)
			add_impl(x);
	}

	void add_impl(ll x) {
		int p = x & (table.size() - 1);
		while (table[p] != -1)
			p = (p+1) & (table.size() - 1);
		table[p] = x;
	}

	void add(ll x) {
		if (content.size() * 4 == table.size())
			expand();
		add_impl(x);
		content.push_back(x);
	}

	int count(ll x) const {
		int p = x & (table.size() - 1);
		while (table[p] != -1) {
			if (table[p] == x)
				return 1;
			p = (p+1) & (table.size() - 1);
		}
		return 0;
	}
};

htable dodato[150005], obrisano[150005];
vector<int> velicine;

void dodaj_velicinu(int x) {
	auto it = lower_bound(velicine.begin(), velicine.end(), x);
	if (it != velicine.end() && *it == x)
		return;
	velicine.push_back(x);
	int i = velicine.size() - 1;
	while (i > 0 && velicine[i-1] > velicine[i]) {
		swap(velicine[i-1], velicine[i]);
		i--;
	}
}

mint1 p1[300005];
mint2 p2[300005];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	p1[0] = 1;
	p2[0] = 1;

	for (int i=1; i<300005; i++) {
		p1[i] = p1[i-1] * 127;
		p2[i] = p2[i-1] * 129;
	}

	int q;
	cin >> q;
	while (q--) {
		int t;
		string s;
		cin >> t >> s;

		if (t < 3) {

			if (s.size() > 150000)
				continue; // cool

			mint1 h1;
			mint2 h2;

			for (char x : s) {
				h1 = h1 * 127 + x;
				h2 = h2 * 129 + x;
			}

			auto gde = t == 1 ? dodato : obrisano;
			ll hv = (int)h1 * 1123123123ll + (int)h2;
			gde[s.size()].add(hv);
			dodaj_velicinu(s.size());
		} else {

			int ans = 0;

			for (int vel : velicine) {
				if (vel > (int)s.size())
					break;
				mint1 h1;
				mint2 h2;
				for (int i=0; i<vel; i++) {
					h1 = h1 * 127 + s[i];
					h2 = h2 * 129 + s[i];
				}

				ll hv = (int)h1 * 1123123123ll + (int)h2;

				for (int i=vel; i<=(int)s.size(); i++) {
					// proveri
					ans += dodato[vel].count(hv) - obrisano[vel].count(hv);
					// pomeri
					if (i == (int)s.size())
						break;
					h1 = h1 * 127 + s[i] - p1[vel] * s[i-vel];
					h2 = h2 * 129 + s[i] - p2[vel] * s[i-vel];
					hv = (int)h1 * 1123123123ll + (int)h2;
				}
			}

			cout << ans << '\n' << flush;
		}
	}
}


#pragma GCC optimize("O3")
#pragma GCC target("tune=native")
#pragma GCC optimize("fast-math")

#include <math.h>
#include <algorithm>
#include <set>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <time.h>
#include <cassert>
#include <functional>
#include <memory.h>
#include <stack>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <chrono>
#include <complex>
#include <fstream>
#include <climits>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef unsigned u;
typedef long double ld;
typedef vector<vector<int>> vvi;
typedef unsigned char uc;
typedef unsigned short us;
typedef complex<double> cd;

#define INF 1000000000
#define LLINF 1000000000000000000LL
#define EPS 1e-9l
#define pii pair<int, int>

const int DEBUG = 0;

mt19937 gen((u)chrono::high_resolution_clock::now().time_since_epoch().count());

#pragma comment(linker, "/STACK:16777216")

const int A = 26;
const int LOG = 19;
const int N = (int)3e5 + 100;

struct node
{
	int link;
	int p;
	int to[A];
	int next[A];
	char c;
	int cnt;
	int occ;

	node(char _c = -1, int _p = -1, int _cnt = 0, int _link = -1)
	{
		c = _c;
		p = _p;
		cnt = _cnt;
		link = _link;
		occ = -1;

		fill(to, to + A, -1);
		fill(next, next + A, -1);
	}
};

struct trie
{
	int string_cnt;
	vector<node> vtx;
	int lid;

	trie()
	{
		string_cnt = 0;
		lid = 1;
		vtx.emplace_back(node());
	}

	void add(const string& s)
	{
		string_cnt++;
		int v = 0;

		for (char c : s)
		{
			c -= 'a';

			if (vtx[v].to[c] == -1)
			{
				vtx.emplace_back(node());
				vtx[v].to[c] = lid++;
				vtx[vtx[v].to[c]].p = v;
				vtx[vtx[v].to[c]].c = c;
			}

			v = vtx[v].to[c];
		}

		vtx[v].cnt++;
	}

	int size() const
	{
		return string_cnt;
	}

	int go(int v, int c)
	{
		if (vtx[v].next[c] == -1)
		{
			if (vtx[v].to[c] != -1)
				vtx[v].next[c] = vtx[v].to[c];
			else if (v == 0)
				vtx[v].next[c] = 0;
			else
				vtx[v].next[c] = go(link(v), c);
		}

		return vtx[v].next[c];
	}

	int link(int v)
	{
		if (vtx[v].link == -1)
		{
			if (v == 0 || vtx[v].p == 0)
				vtx[v].link = 0;
			else
				vtx[v].link = go(link(vtx[v].p), vtx[v].c);
		}

		return vtx[v].link;
	}

	void clear()
	{
		vtx = {};
		vtx.emplace_back(node());
		string_cnt = 0;
		lid = 1;
	}

	int calc(int v)
	{
		int& ret = vtx[v].occ;

		if (ret == -1)
		{
			ret = vtx[v].cnt;

			if (link(v) != -1)
				ret += calc(link(v));
		}

		return ret;
	}

	ll count(const string& s)
	{
		if (size() == 0)
			return 0;

		ll res = 0;
		int v = 0;

		for (char c : s)
		{
			c -= 'a';
			v = go(v, c);

			res += calc(v);
		}

		return res;
	}
};

void dfs(trie& a, trie& b, int v, int u)
{
	b.vtx[u].cnt += a.vtx[v].cnt;

	for (int i = 0; i < A; i++)
	{
		if (a.vtx[v].to[i] == -1)
			continue;

		if (b.vtx[u].to[i] == -1)
		{
			b.vtx.emplace_back(node());
			b.vtx[u].to[i] = b.lid++;
			b.vtx[b.lid - 1].c = i;
			b.vtx[b.lid - 1].p = u;
		}

		dfs(a, b, a.vtx[v].to[i], b.vtx[u].to[i]);
	}
}

//a ������� � b
void merge(trie& a, trie& b)
{
	dfs(a, b, 0, 0);

	for (int i = 0; i < b.lid; i++)
	{
		node& t = b.vtx[i];

		fill(t.next, t.next + A, -1);
		t.link = -1;
	}

	b.string_cnt += a.string_cnt;
	a.clear();
}

trie have[LOG];
trie bad[LOG];

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.setf(cout.fixed);
	cout.precision(12);
	auto START_TIME = chrono::high_resolution_clock::now();

	int q;
	cin >> q;

	while (q--)
	{
		int type;
		cin >> type;

		if (type == 1)
		{
			string s;
			cin >> s;

			have[0].add(s);

			for (int i = 0, max_sz = 2; i < LOG; i++, max_sz *= 2)
			{
				if (have[i].size() == max_sz)
					merge(have[i], have[i + 1]);
				else
					break;
			}
		}
		else if (type == 2)
		{
			string s;
			cin >> s;

			bad[0].add(s);

			for (int i = 0, max_sz = 2; i < LOG; i++, max_sz *= 2)
			{
				if (bad[i].size() == max_sz)
					merge(bad[i], bad[i + 1]);
				else
					break;
			}
		}
		else
		{
			string s;
			cin >> s;

			ll res = 0;

			for (int i = 0; i < LOG; i++)
				res += have[i].count(s) - bad[i].count(s);

			cout << res << endl;
		}
	}

#ifdef LOCAL
	cerr.precision(3);
	cerr << "\nWorking time: " << chrono::duration<double>(chrono::high_resolution_clock::now() - START_TIME).count() << " sec.";
#endif

	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 21;
const int K = 26;
const int M = 20;
struct Node {
	int* to;
	bool root;
	int p;
	int pchar;
	int* go;
	int sum;
	int term;
	int suf_link;
	Node() {
		to = new int[K];
		go = new int[K];
		memset(to, -1, K * sizeof(int));
		memset(go, -1, K * sizeof(int));

		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);
		}
	}
	return ans;
}

void clean(int v) {
	for (int i = 0; i < K; i++) {
		if (node[v].to[i] != -1)
			clean(node[v].to[i]);
	}
	delete node[v].to;
	delete node[v].go;
}

void insert(string s, int idx) {
	str[idx][0].push_back(s);
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();

			clean(roots[idx][k]);
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	assert(kk != -1);
	clean(roots[idx][kk]);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	for (int idx = 0; idx < 2; idx++) {
		for (int i = 0; i < M; i++) {
			roots[idx][i] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
	}

	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 21;
const int K = 26;
const int M = 20;
struct Node {
	int* to;
	bool root;
	int p;
	int pchar;
	int* go;
	int sum;
	int term;
	int suf_link;
	Node() {
		to = new int[K];
		go = new int[K];
		for (int i = 0; i < K; i++) {
			to[i] = go[i] = -1;
		}
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);
		}
	}
	return ans;
}

void clean(int v) {
	for (int i = 0; i < K; i++) {
		if (node[v].to[i] != -1)
			clean(node[v].to[i]);
	}
	delete node[v].to;
	delete node[v].go;
}

void insert(string s, int idx) {
	str[idx][0].push_back(s);
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();

			clean(roots[idx][k]);
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	assert(kk != -1);
	clean(roots[idx][kk]);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	for (int idx = 0; idx < 2; idx++) {
		for (int i = 0; i < M; i++) {
			roots[idx][i] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
	}

	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 10;
const int K = 26;
const int M = 20;
struct Node {
	int to[K];
	bool root;
	int p;
	int pchar;
	int go[K];
	int sum;
	int term;
	int suf_link;
	Node() {
		memset(to, -1, sizeof to);
		memset(go, -1, sizeof go);
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		//	cout << i << ' ' << str[0][i].back() << endl;
		//	cout << "STR B "  << calc(s, roots[0][i]) << endl;
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);

			//cout << "STR A " << calc(s, roots[1][i]) << endl;
		}
	}
	return ans;
}
void insert(string s, int idx) {
	str[idx][0].push_back(s);
	//cout << "insert" << s << " " << idx << endl;
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	//cout << "KK" << ' ' << kk << endl;
	assert(kk != -1);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 10;
const int K = 26;
const int M = 20;
struct Node {
	vector<int> to;
	bool root;
	int p;
	int pchar;
	vector<int> go;
	int sum;
	int term;
	int suf_link;
	Node() {
		to = vector<int>(K, -1);
		go = vector<int>(K, -1);
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);
		}
	}
	return ans;
}

void clean(int v) {
	for (int i = 0; i < K; i++) {
		if (node[v].to[i] != -1)
			clean(node[v].to[i]);
	}
	node[v].go.clear();
	node[v].go.shrink_to_fit();
	node[v].to.clear();
	node[v].to.shrink_to_fit();
}

void insert(string s, int idx) {
	str[idx][0].push_back(s);
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();

			clean(roots[idx][k]);
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	assert(kk != -1);
	clean(roots[idx][kk]);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	for (int idx = 0; idx < 2; idx++) {
		for (int i = 0; i < M; i++) {
			roots[idx][i] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
	}
	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 10;
const int K = 26;
const int M = 20;
struct Node {
	int to[K];
	bool root;
	int p;
	int pchar;
	int go[K];
	int sum;
	int term;
	int suf_link;
	Node() {
		memset(to, -1, sizeof to);
		memset(go, -1, sizeof go);
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		//	cout << i << ' ' << str[0][i].back() << endl;
		//	cout << "STR B "  << calc(s, roots[0][i]) << endl;
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);

			//cout << "STR A " << calc(s, roots[1][i]) << endl;
		}
	}
	return ans;
}
void insert(string s, int idx) {
	str[idx][0].push_back(s);
	//cout << "insert" << s << " " << idx << endl;
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	//cout << "KK" << ' ' << kk << endl;
	assert(kk != -1);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 10;
const int K = 26;
const int M = 20;
struct Node {
	vector<int> to;
	bool root;
	int p;
	int pchar;
	vector<int> go;
	int sum;
	int term;
	int suf_link;
	Node() {
		to = vector<int>(K, -1);
		go = vector<int>(K, -1);
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);
		}
	}
	return ans;
}

void clean(int v) {
	for (int i = 0; i < K; i++) {
		if (node[v].to[i] != -1)
			clean(node[v].to[i]);
	}
	node[v].go.clear();
	node[v].to.clear();
}

void insert(string s, int idx) {
	str[idx][0].push_back(s);
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();

			clean(roots[idx][k]);
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	assert(kk != -1);
	clean(roots[idx][kk]);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	for (int idx = 0; idx < 2; idx++) {
		for (int i = 0; i < M; i++) {
			roots[idx][i] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
	}
	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;
#define mp make_pair

typedef long long li;
const int N = 3e5 + 21;
const int K = 26;
const int M = 20;
struct Node {
	int* to;
	bool root;
	int p;
	int pchar;
	int* go;
	int sum;
	int term;
	int suf_link;
	Node() {
		to = new int[K];
		go = new int[K];
		for (int i = 0; i < K; i++) {
			to[i] = go[i] = -1;
		}
		p = -1;
		suf_link = -1;
		pchar = -1;
		term = 0;
		root = false;
		sum = -1;
	}
};

vector <Node> node;
int roots[2][M];
vector <string> str[2][M];

void add(int root, string s) {
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		if (node[v].to[c] == -1) {
			Node t;
			t.p = v;
			t.pchar = c;
			node[v].to[c] = node.size();
			node.push_back(t);
		}
		v = node[v].to[c];
	}
	node[v].term++;
}

int go(int v, int c);
int suf_link(int v) {
	if (node[v].suf_link != -1) return node[v].suf_link;
	if (node[v].root) {
		return node[v].suf_link = v;
	}
	if (node[node[v].p].root) {
		return node[v].suf_link = node[v].p;
	}
	return node[v].suf_link = go(suf_link(node[v].p), node[v].pchar);
}

int go(int v, int c) {
	if (node[v].go[c] != -1) return node[v].go[c];
	if (node[v].to[c] != -1) return node[v].go[c] = node[v].to[c];
	if (node[v].root) {
		return v;
	}
	return node[v].go[c] = go(suf_link(v), c);
}

int sum(int v) {
	if (node[v].sum != -1) return node[v].sum;
	node[v].sum = node[v].term;
	if (!node[v].root) node[v].sum += sum(suf_link(v));
	return node[v].sum;
}

li calc(const string& s, int root) {
	li ans = 0;
	int v = root;
	for (int i = 0; i < s.length(); i++) {
		int c = s[i] - 'a';
		v = go(v, c);
		ans += sum(v);
	}
	return ans;
}
li result(string s){
	li ans = 0;
	for (int i = 0; i < M; i++) {
		if (str[0][i].size() != 0) {
			ans += calc(s, roots[0][i]);
		}
		if (str[1][i].size() != 0) {
			ans -= calc(s, roots[1][i]);
		}
	}
	return ans;
}

void clean(int v) {
	for (int i = 0; i < K; i++) {
		if (node[v].to[i] != -1)
			clean(node[v].to[i]);
	}
}

void insert(string s, int idx) {
	str[idx][0].push_back(s);
	int kk = -1;
	for (int k = 0; k < M; k++) {
		if (str[idx][k].size() == (1 << (k + 1))) {
			for (int i = 0; i < str[idx][k].size(); i++) {
				str[idx][k + 1].push_back(str[idx][k][i]);
			}
			str[idx][k].clear();

			clean(roots[idx][k]);
			roots[idx][k] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
		else {
			kk = k;
			break;
		}
	}
	assert(kk != -1);
	clean(roots[idx][kk]);
	roots[idx][kk] = (int)node.size();
	node.push_back(Node());
	node.back().root = 1;
	for (int i = 0; i < str[idx][kk].size(); i++) {
		add(roots[idx][kk], str[idx][kk][i]);
	}
}

char stroch[N];
int main() {
#if _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	for (int idx = 0; idx < 2; idx++) {
		for (int i = 0; i < M; i++) {
			roots[idx][i] = (int)node.size();
			node.push_back(Node());
			node.back().root = 1;
		}
	}

	int n;
	scanf(" %d", &n);
	for (int i = 0; i < n; i++) {
		int type;
		scanf(" %d", &type);
		scanf(" %s", stroch);
		string s = string(stroch);
		if (type != 3) {
			insert(s, type - 1);
		}
		else {
			printf(" %I64d\n", result(s));
			fflush(stdout);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>

typedef long long ll;

using namespace std;

// !!!aho
struct aho
{
	static const int A = 26;
	struct vert
	{
		vert* ch[A];
		vert* p;
		vert* l;
		int cnt;
		int cnt1;
		char c;
		char d[3];
		void init(){
			p = (vert*)-1;
			l = (vert*)-1;
			c = -1;
			cnt = 0;
			cnt1 = int(1<<31);
			for (int i=0; i<A; ++i)
				ch[i] = (vert*)-1;
		}
	};
	vector<vert> verts;
	int left, right;
	int leftc, rightc;
	aho()
	{
		clear();
		verts.reserve(1<<17);
		left = 0;
		right = 0;
		leftc = 0;
		rightc = 0;
	}
	void clear()
	{
		verts.resize(1);
		verts[0].init();
		verts[0].p = (vert*)0;
		verts[0].cnt1 = 0;
	}
	void add(const string &s, int w)
	{
		int v = 0, tmp;
		for (int i=0; i<s.length(); ++i)
		{
			char c = s[i]-'a';
			tmp = (int)verts[v].ch[c];
			if (tmp < 0)
			{
				tmp = verts.size();
				verts.resize(tmp+1);
				verts[tmp].init();
				verts[tmp].p = (vert*)v;
				verts[tmp].c = c;
				verts[v].ch[c] = (vert*)tmp;
			}
			v = tmp;
		}
		verts[v].cnt += w;
	}

	vert* move(vert *v, char c)
	{
		vert **r = &v->ch[c];
		if (*r == 0)
			*r = move(link(v), c);
		return *r;
	}
	vert* link(vert* v)
	{
		vert **r = &v->l;
		if (*r == 0)
			*r = move(link(v->p), v->c);
		return *r;
	}
	int dcnt(vert *v)
	{
		int &r = v->cnt1;
		if (r == int(1<<31))
			r = v->cnt+dcnt(link(v));
		return r;
	}
	void convert(vert **x)
	{
		if (int(*x) < 0)
			*x = 0;
		else
			*x = &verts[int(*x)];
	}
	void build()
	{
		for (int i=0; i<verts.size(); ++i)
		{
			convert(&verts[i].p);
			convert(&verts[i].l);
			for(int j=0; j<A; ++j)
				convert(&verts[i].ch[j]);
		}
		verts[0].l = &verts[0];
		for (int i=0; i<A; ++i)
		{
			if (verts[0].ch[i] == 0)
			{
				verts[0].ch[i] = &verts[0];
			}
			else
			{
				verts[0].ch[i]->l = &verts[0];
			}
		}
		for (int i=0; i<verts.size(); ++i)
		{
			vert *v = &verts[i];
			link(v);
			dcnt(v);
			for (int j=0; j<A; ++j)
				move(v, j);
		}
	}
};

void solve()
{
	vector<aho> ah(20);
	int acnt = 0;
	vector<pair<int, string>> q;
	int Q;
	scanf("%d", &Q);
	for (int i=0; i<Q; ++i)
	{
		int x;
		string s;
		cin >> x >> s;
		if (x == 3)
		{
			ll z = 0;
			int qn = q.size();
			//printf("? %d\n", acnt);
			for (int p=0; p<acnt; ++p)
			{
				aho &a = ah[p];
				aho::vert *v = &a.verts[0];
				for (int i=0; i<s.length(); ++i)
				{
					char c = s[i]-'a';
					v = v->ch[c];
					z += v->cnt1;
				}
			}
			printf("%I64d\n", z);
			fflush(stdout);
		}
		else
		{
			q.push_back(pair<int, string>(x, s));
			int qn = q.size();
			ah[acnt].left = qn-1;
			ah[acnt].right = qn;
			ah[acnt].leftc = (acnt ? ah[acnt-1].rightc : 0);
			ah[acnt].rightc = ah[acnt].leftc+s.length();
			for (int p=0; p<=acnt; ++p)
			{
				if (p == acnt || ah[p].rightc-ah[p].leftc <= ah[acnt].rightc-ah[p].rightc)
				{
					//printf("p=%d l=%d r=%d lc=%d rc=%d ac=%d arc=%d\n", p, ah[p].left, ah[p].right, ah[p].leftc, ah[p].rightc, acnt, ah[acnt].rightc);
					aho &a = ah[p];
					a.clear();
					a.right = qn;
					a.rightc = ah[acnt].rightc;
					for (int i=a.left; i<a.right; ++i)
					{
						a.add(q[i].second, q[i].first==1?1:-1);
					}
					a.build();
					for (int zz = p+1; zz<acnt; ++zz)
						ah[zz].clear();
					acnt = p+1;
					break;
				}
			}
		}
	}
}

int main()
{
	solve();
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>

typedef long long ll;

using namespace std;

// !!!aho
struct aho
{
	static const int A = 26;
	struct vert
	{
		vert* ch[A];
		vert* p;
		vert* l;
		int cnt;
		int cnt1;
		char c;
		char d[3];
		void init(){
			p = (vert*)-1;
			l = (vert*)-1;
			c = -1;
			cnt = 0;
			cnt1 = int(1<<31);
			for (int i=0; i<A; ++i)
				ch[i] = (vert*)-1;
		}
	};
	vector<vert> verts;
	int left, right;
	int leftc, rightc;
	aho()
	{
		clear();
		verts.reserve(1<<17);
		left = 0;
		right = 0;
		leftc = 0;
		rightc = 0;
	}
	void clear()
	{
		verts.resize(1);
		verts[0].init();
		verts[0].p = (vert*)0;
		verts[0].cnt1 = 0;
	}
	void add(const string &s, int w)
	{
		int v = 0, tmp;
		for (int i=0; i<s.length(); ++i)
		{
			char c = s[i]-'a';
			tmp = (int)verts[v].ch[c];
			if (tmp < 0)
			{
				tmp = verts.size();
				verts.resize(tmp+1);
				verts[tmp].init();
				verts[tmp].p = (vert*)v;
				verts[tmp].c = c;
				verts[v].ch[c] = (vert*)tmp;
			}
			v = tmp;
		}
		verts[v].cnt += w;
	}

	vert* move(vert *v, char c)
	{
		vert **r = &v->ch[c];
		if (*r == 0)
			*r = move(link(v), c);
		return *r;
	}
	vert* link(vert* v)
	{
		vert **r = &v->l;
		if (*r == 0)
			*r = move(link(v->p), v->c);
		return *r;
	}
	int dcnt(vert *v)
	{
		int &r = v->cnt1;
		if (r == int(1<<31))
			r = v->cnt+dcnt(link(v));
		return r;
	}
	void convert(vert **x)
	{
		if (int(*x) < 0)
			*x = 0;
		else
			*x = &verts[int(*x)];
	}
	void build()
	{
		for (int i=0; i<verts.size(); ++i)
		{
			convert(&verts[i].p);
			convert(&verts[i].l);
			for(int j=0; j<A; ++j)
				convert(&verts[i].ch[j]);
		}
		verts[0].l = &verts[0];
		for (int i=0; i<A; ++i)
		{
			if (verts[0].ch[i] == 0)
			{
				verts[0].ch[i] = &verts[0];
			}
			else
			{
				verts[0].ch[i]->l = &verts[0];
			}
		}
		/*for (int i=0; i<verts.size(); ++i)
		{
			vert *v = &verts[i];
			link(v);
			dcnt(v);
			for (int j=0; j<A; ++j)
				move(v, j);
		}*/
	}
};

void solve()
{
	vector<aho> ah(20);
	int acnt = 0;
	vector<pair<int, string>> q;
	int Q;
	scanf("%d", &Q);
	for (int i=0; i<Q; ++i)
	{
		int x;
		string s;
		cin >> x >> s;
		if (x == 3)
		{
			ll z = 0;
			int qn = q.size();
			//printf("? %d\n", acnt);
			for (int p=0; p<acnt; ++p)
			{
				aho &a = ah[p];
				aho::vert *v = &a.verts[0];
				for (int i=0; i<s.length(); ++i)
				{
					char c = s[i]-'a';
					v = a.move(v,c);
					z += a.dcnt(v);
				}
			}
			printf("%I64d\n", z);
			fflush(stdout);
		}
		else
		{
			q.push_back(pair<int, string>(x, s));
			int qn = q.size();
			ah[acnt].left = qn-1;
			ah[acnt].right = qn;
			ah[acnt].leftc = (acnt ? ah[acnt-1].rightc : 0);
			ah[acnt].rightc = ah[acnt].leftc+s.length();
			for (int p=0; p<=acnt; ++p)
			{
				if (p == acnt || ah[p].rightc-ah[p].leftc <= ah[acnt].rightc-ah[p].rightc)
				{
					//printf("p=%d l=%d r=%d lc=%d rc=%d ac=%d arc=%d\n", p, ah[p].left, ah[p].right, ah[p].leftc, ah[p].rightc, acnt, ah[acnt].rightc);
					aho &a = ah[p];
					a.clear();
					a.right = qn;
					a.rightc = ah[acnt].rightc;
					for (int i=a.left; i<a.right; ++i)
					{
						a.add(q[i].second, q[i].first==1?1:-1);
					}
					a.build();
					for (int zz = p+1; zz<acnt; ++zz)
						ah[zz].clear();
					acnt = p+1;
					break;
				}
			}
		}
	}
}

int main()
{
	solve();
	return 0;
}