import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
public class Main {
public static void main(String[] args) throws IOException{
InputReader in = new InputReader(new FileInputStream("trie.in"));
//InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter("trie.out");
//PrintWriter out = new PrintWriter(System.out);
Trie T = new Trie();
int op;
while (in.hasNext()) {
op = in.nextInt();
String S = in.nextString();
if (op == 0)
T.insert(S);
else if (op == 1)
T.erase(S);
else if (op == 2)
out.println(T.count(S));
else
out.println(T.prefix(S));
}
out.close();
}
private static class Trie {
private class Node {
int cnt, nr;
Node[] links;
Node() {
links = new Node[26];
cnt = nr = 0;
}
}
private Node root;
Trie() {
root = new Node();
}
public void insert(String S) {
Node p = root;
for (int i = 0; i < S.length(); ++i) {
int x = S.charAt(i) - 'a';
if (p.links[x] == null) {
p.links[x] = new Node();
p.nr++;
}
p = p.links[x];
}
p.cnt++;
}
public void erase(String S) {
Node[] nodes = new Node[S.length() + 1];
nodes[0] = root;
for (int i = 0; i < S.length(); ++i) {
int x = S.charAt(i) - 'a';
nodes[i + 1] = nodes[i].links[x];
}
nodes[S.length()].cnt--;
for (int i = S.length() - 1; i >= 0; --i) {
int x = S.charAt(i) - 'a';
if (nodes[i + 1].cnt == 0 && nodes[i + 1].nr == 0) {
nodes[i].links[x] = null;
nodes[i].nr--;
}
}
}
public int count(String S) {
Node p = root;
for (int i = 0; i < S.length(); ++i) {
int x = S.charAt(i) - 'a';
if (p.links[x] == null)
return 0;
p = p.links[x];
}
return p.cnt;
}
public int prefix(String S) {
Node p = root;
for (int i = 0; i < S.length(); ++i) {
int x = S.charAt(i) - 'a';
if (p.links[x] == null)
return i;
p = p.links[x];
}
return S.length();
}
}
}
class InputReader {
private InputStream stream;
private byte[] buf = new byte[4096];
private int curChar;
private int numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int peek() {
if (numChars == -1)
return -1;
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
return -1;
}
if (numChars <= 0)
return -1;
}
return buf[curChar];
}
public void skip(int x) {
while (x-- > 0)
read();
}
public int nextInt() {
return Integer.parseInt(nextString());
}
public long nextLong() {
return Long.parseLong(nextString());
}
public String nextString() {
int c = read();
while (isSpaceChar(c))
c = read();
StringBuffer res = new StringBuffer();
do {
res.appendCodePoint(c);
c = read();
} while (!isSpaceChar(c));
return res.toString();
}
public String next() {
return nextString();
}
public String nextLine() {
StringBuffer buf = new StringBuffer();
int c = read();
while (c != '\n' && c != -1) {
if (c != '\r')
buf.appendCodePoint(c);
c = read();
}
return buf.toString();
}
public double nextDouble() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
double res = 0;
while (!isSpaceChar(c) && c != '.') {
if (c == 'e' || c == 'E')
return res * Math.pow(10, nextInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
}
if (c == '.') {
c = read();
double m = 1;
while (!isSpaceChar(c)) {
if (c == 'e' || c == 'E')
return res * Math.pow(10, nextInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
m /= 10;
res += (c - '0') * m;
c = read();
}
}
return res * sgn;
}
public boolean hasNext() {
int value;
while (isSpaceChar(value = peek()) && value != -1)
read();
return value != -1;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}