During the archaeological research in the Middle East you found the traces of three ancient religions: First religion, Second religion and Third religion. You compiled the information on the evolution of each of these beliefs, and you now wonder if the followers of each religion could coexist in peace.

The Word of Universe is a long word containing the lowercase English characters only. At each moment of time, each of the religion beliefs could be described by a word consisting of lowercase English characters.

The three religions can coexist in peace if their descriptions form disjoint subsequences of the Word of Universe. More formally, one can paint some of the characters of the Word of Universe in three colors: 1, 2, 3, so that each character is painted in at most one color, and the description of the i-th religion can be constructed from the Word of Universe by removing all characters that aren't painted in color i.

The religions however evolve. In the beginning, each religion description is empty. Every once in a while, either a character is appended to the end of the description of a single religion, or the last character is dropped from the description. After each change, determine if the religions could coexist in peace.

Input

The first line of the input contains two integers n, q (1 ≤ n ≤ 100 000, 1 ≤ q ≤ 1000) — the length of the Word of Universe and the number of religion evolutions, respectively. The following line contains the Word of Universe — a string of length n consisting of lowercase English characters.

Each of the following line describes a single evolution and is in one of the following formats: 

  * + i c (i ∈ \{1, 2, 3\}, c ∈ \{a, b, ..., z\}: append the character c to the end of i-th religion description. 
  * - i (i ∈ \{1, 2, 3\}) – remove the last character from the i-th religion description. You can assume that the pattern is non-empty. 



You can assume that no religion will have description longer than 250 characters.

Output

Write q lines. The i-th of them should be YES if the religions could coexist in peace after the i-th evolution, or NO otherwise.

You can print each character in any case (either upper or lower).

Examples

Input


6 8
abdabc
+ 1 a
+ 1 d
+ 2 b
+ 2 c
+ 3 a
+ 3 b
+ 1 c
- 2


Output


YES
YES
YES
YES
YES
YES
NO
YES


Input


6 8
abbaab
+ 1 a
+ 2 a
+ 3 a
+ 1 b
+ 2 b
+ 3 b
- 1
+ 2 z


Output


YES
YES
YES
YES
YES
NO
YES
NO

Note

In the first example, after the 6th evolution the religion descriptions are: ad, bc, and ab. The following figure shows how these descriptions form three disjoint subsequences of the Word of Universe:

<image>
1 1
t
+ 2 p
 2 12
aa
+ 1 a
+ 2 a
+ 3 a
- 1
+ 1 a
- 2
+ 2 a
- 3
+ 3 a
+ 2 a
- 1
- 3
 2 10
uh
+ 1 h
+ 2 u
+ 3 h
- 1
- 2
+ 2 h
+ 3 u
- 2
+ 1 u
- 3
 1 1
z
+ 3 z

NO
 YES
YES
NO
YES
NO
YES
NO
YES
NO
NO
NO
YES
 YES
YES
NO
YES
YES
NO
NO
NO
NO
YES
 YES

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.FilterInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * @author khokharnikunj8
 */

public class Main {
    public static void main(String[] args) {
        new Thread(null, new Runnable() {
            public void run() {
                new Main().solve();
            }
        }, "1", 1 << 26).start();
    }

    void solve() {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        ScanReader in = new ScanReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DThreeReligions solver = new DThreeReligions();
        solver.solve(1, in, out);
        out.close();
    }

    static class DThreeReligions {
        char[][] sb;
        int[] size;
        BSTCustom<Integer>[] index;
        char[] ar;

        public boolean checker() {
            int[][] which = new int[][]{{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {2, 0, 1}, {1, 2, 0}, {2, 1, 0}};
            out:
            for (int[] perm : which) {
                ArrayList<Integer> temp = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    int last = -1;
                    for (int j = 0; j < size[perm[i]]; j++) {
                        int nono = (int) index[sb[perm[i]][j] - 'a'].lower_bound(last);
                        if (nono == index[sb[perm[i]][j] - 'a'].size()) {
                            for (int LOl : temp) index[ar[LOl] - 'a'].insert(LOl);
                            continue out;
                        }
                        last = index[sb[perm[i]][j] - 'a'].get(nono);
                        index[sb[perm[i]][j] - 'a'].remove(last);
                        temp.add(last);

                    }
                }
                for (int LOl : temp) index[ar[LOl] - 'a'].insert(LOl);
                return true;
            }
            return false;
        }

        public void solve(int testNumber, ScanReader in, PrintWriter out) {
            int n = in.scanInt();
            int q = in.scanInt();
            ar = in.scanString().toCharArray();
            index = new BSTCustom[26];
            for (int i = 0; i < 26; i++) index[i] = new BSTCustom<Integer>();
            for (int i = 0; i < n; i++) index[ar[i] - 'a'].insert(i);
            sb = new char[3][251];
            size = new int[3];
            while (q-- > 0) {
                char type = in.scanChar();
                if (type == '+') {
                    int i = in.scanInt() - 1;
                    char c = in.scanChar();
                    sb[i][size[i]++] = c;
                } else {
                    int i = in.scanInt() - 1;
                    size[i]--;
                }
                if (checker()) out.println("YES");
                else out.println("NO");
            }
        }

    }

    static class ScanReader {
        private byte[] buf = new byte[4 * 1024];
        private int index;
        private BufferedInputStream in;
        private int total;

        public ScanReader(InputStream inputStream) {
            in = new BufferedInputStream(inputStream);
        }

        private int scan() {
            if (index >= total) {
                index = 0;
                try {
                    total = in.read(buf);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (total <= 0) return -1;
            }
            return buf[index++];
        }

        public char scanChar() {
            int c = scan();
            while (isWhiteSpace(c)) c = scan();
            return (char) c;
        }

        public int scanInt() {
            int integer = 0;
            int n = scan();
            while (isWhiteSpace(n)) n = scan();
            int neg = 1;
            if (n == '-') {
                neg = -1;
                n = scan();
            }
            while (!isWhiteSpace(n)) {
                if (n >= '0' && n <= '9') {
                    integer *= 10;
                    integer += n - '0';
                    n = scan();
                }
            }
            return neg * integer;
        }

        public String scanString() {
            int c = scan();
            if (c == -1) return null;
            while (isWhiteSpace(c)) c = scan();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = scan();
            } while (!isWhiteSpace(c));
            return res.toString();
        }

        private boolean isWhiteSpace(int n) {
            if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
            else return false;
        }

    }

    static class BSTCustom<T extends Comparable<? super T>> {
        private Node<T> __root;
        private Node<T> __tempnode;
        private Node<T> __tempnode1;
        private long __size;
        private boolean __multi;

        public BSTCustom() {
            __root = null;
            __size = 0;
            __multi = false;

        }

        public BSTCustom(boolean __multi) {
            __root = null;
            __size = 0;
            this.__multi = __multi;
        }

        public long lower_bound(T data) {
            __tempnode = __root;
            long index = 0;
            while (__tempnode != null) {
                int _comparator = data.compareTo(__tempnode.data);
                if (_comparator < 0) {
                    __tempnode = __tempnode._left;
                } else if (_comparator > 0) {
                    index += (__tempnode.count + __tempnode._leftside);
                    __tempnode = __tempnode._right;
                } else {
                    index += (__tempnode._leftside);
                    break;
                }
            }
            return index;
        }

        private Node<T> remove(Node<T> temp, T data, long count) {
            if (temp == null) return temp;
            int _comparator = data.compareTo(temp.data);
            if (_comparator < 0) temp._left = remove(temp._left, data, count);
            else if (_comparator > 0) temp._right = remove(temp._right, data, count);
            else {
                if (__multi && count < temp.count && temp.count > 1) {
                    __size -= count;
                    temp.count -= count;
                } else {
                    __size -= temp.count;
                    if (temp._left == null && temp._right == null) return null;
                    else if (temp._left == null) return temp._right;
                    else if (temp._right == null) return temp._left;
                    else {
                        __tempnode = minValue(temp._right);
                        temp.data = __tempnode.data;
                        temp.count = __tempnode.count;
                        temp._right = remove(temp._right, __tempnode.data, __tempnode.count);
                        __size += temp.count;
                    }
                }
            }
            // for __leftside and _rightside count
            if (temp._left != null)
                temp._leftside = temp._left._leftside + temp._left._rightside + temp._left.count;
            else temp._leftside = 0;
            if (temp._right != null)
                temp._rightside = temp._right._leftside + temp._right._rightside + temp._right.count;
            else temp._rightside = 0;

            temp._height = Math.max(getheight(temp._left), getheight(temp._right)) + 1;
            //Balancing

            long diff = getDiff(temp);
            if (diff > 1) {
                if (getDiff(temp._left) >= 0) {
                    temp = rightRotate(temp);
                } else {
                    temp._left = leftRotate(temp._left);
                    temp = rightRotate(temp);
                }
            } else if (diff < -1) {
                if (getDiff(temp._right) <= 0) {
                    temp = leftRotate(temp);
                } else {
                    temp._right = rightRotate(temp._right);
                    temp = leftRotate(temp);
                }
            }
            return temp;
        }

        public T get(long index) {
            __tempnode = __root;
            long current = 0;
            while (__tempnode != null) {
                if (__tempnode._left == null) {
                    if (__tempnode.count + current > index) return __tempnode.data;
                    else {
                        current += __tempnode.count;
                        __tempnode = __tempnode._right;
                    }
                } else {
                    if (current + __tempnode._leftside > index) __tempnode = __tempnode._left;
                    else if (current + __tempnode._leftside + __tempnode.count > index)
                        return __tempnode.data;
                    else {
                        current += __tempnode.count + __tempnode._leftside;
                        __tempnode = __tempnode._right;
                    }

                }
            }
            return null;
        }

        private Node<T> minValue(Node<T> temp) {
            __tempnode = temp;
            while (__tempnode._left != null) __tempnode = __tempnode._left;
            return __tempnode;
        }

        public void insert(T data, long... count) {
            if (count.length == 0) __root = insert(__root, data, 1);
            else if (count[0] > 0) __root = insert(__root, data, count[0]);

        }

        public void remove(T data, long... count) {
            if (count.length == 0) __root = remove(__root, data, 1);
            else if (count[0] > 0) __root = remove(__root, data, count[0]);

        }

        private Node<T> insert(Node<T> temp, T data, long count) {
            if (temp == null) {
                if (__multi) {
                    __size += count;
                    return new Node<>(data, count);
                } else {
                    __size++;
                    return new Node<>(data);
                }
            }
            int _comparator = data.compareTo(temp.data);
            if (_comparator < 0) temp._left = insert(temp._left, data, count);
            else if (_comparator > 0) temp._right = insert(temp._right, data, count);
            else if (__multi) {
                __size += count;
                temp.count += count;
            }


            // for __leftside and _rightside count
            if (temp._left != null)
                temp._leftside = temp._left._leftside + temp._left._rightside + temp._left.count;
            else temp._leftside = 0;
            if (temp._right != null)
                temp._rightside = temp._right._leftside + temp._right._rightside + temp._right.count;
            else temp._rightside = 0;

            temp._height = Math.max(getheight(temp._left), getheight(temp._right)) + 1;
            //Balancing

            long diff = getDiff(temp);
            if (diff > 1) {
                if (data.compareTo(temp._left.data) < 0) {
                    temp = rightRotate(temp);
                } else if (data.compareTo(temp._left.data) > 0) {
                    temp._left = leftRotate(temp._left);
                    temp = rightRotate(temp);
                }
            } else if (diff < -1) {
                if (data.compareTo(temp._right.data) > 0) {

                    temp = leftRotate(temp);
                } else if (data.compareTo(temp._right.data) < 0) {
                    temp._right = rightRotate(temp._right);
                    temp = leftRotate(temp);
                }
            }
            return temp;

        }

        private Node<T> rightRotate(Node<T> temp) {
            __tempnode = temp._left;
            __tempnode1 = __tempnode._right;

            __tempnode._right = temp;
            temp._left = __tempnode1;

            //height updation
            temp._height = Math.max(getheight(temp._left), getheight(temp._right)) + 1;
            __tempnode._height = Math.max(getheight(__tempnode._left), getheight(__tempnode._right)) + 1;
            //count updation

            if (temp._left != null)
                temp._leftside = temp._left._leftside + temp._left._rightside + temp._left.count;
            else temp._leftside = 0;
            if (temp._right != null)
                temp._rightside = temp._right._leftside + temp._right._rightside + temp._right.count;
            else temp._rightside = 0;

            if (__tempnode._left != null)
                __tempnode._leftside = __tempnode._left._leftside + __tempnode._left._rightside + __tempnode._left.count;
            else __tempnode._leftside = 0;
            if (__tempnode._right != null)
                __tempnode._rightside = __tempnode._right._leftside + __tempnode._right._rightside + __tempnode._right.count;
            else __tempnode._rightside = 0;


            return __tempnode;
        }

        private Node<T> leftRotate(Node<T> temp) {
            __tempnode = temp._right;
            __tempnode1 = __tempnode._left;

            __tempnode._left = temp;
            temp._right = __tempnode1;

            //height updation
            temp._height = Math.max(getheight(temp._left), getheight(temp._right)) + 1;
            __tempnode._height = Math.max(getheight(__tempnode._left), getheight(__tempnode._right)) + 1;
            //count updation

            if (temp._left != null)
                temp._leftside = temp._left._leftside + temp._left._rightside + temp._left.count;
            else temp._leftside = 0;
            if (temp._right != null)
                temp._rightside = temp._right._leftside + temp._right._rightside + temp._right.count;
            else temp._rightside = 0;


            if (__tempnode._left != null)
                __tempnode._leftside = __tempnode._left._leftside + __tempnode._left._rightside + __tempnode._left.count;
            else __tempnode._leftside = 0;
            if (__tempnode._right != null)
                __tempnode._rightside = __tempnode._right._leftside + __tempnode._right._rightside + __tempnode._right.count;
            else __tempnode._rightside = 0;

            return __tempnode;
        }

        private long getDiff(Node<T> temp) {
            if (temp == null) return 0;
            return getheight(temp._left) - getheight(temp._right);
        }

        public long getheight(Node<T> temp) {
            if (temp == null) return 0;
            return temp._height;
        }

        public long size() {
            return this.__size;
        }

        private class Node<T> {
            T data;
            Node<T> _left;
            Node<T> _right;
            long _leftside;
            long _rightside;
            long _height;
            long count;

            public Node(T data) {
                this.data = data;
                this._left = null;
                this._right = null;
                this._leftside = 0;
                this._rightside = 0;
                this._height = 1;
                this.count = 1;
            }

            public Node(T data, long count) {
                this.data = data;
                this._left = null;
                this._right = null;
                this._leftside = 0;
                this._rightside = 0;
                this._height = 1;
                this.count = count;
            }

        }

    }
}

