#include<bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
// typedef tree<pair<int,int>, null_type, less<pair<int,int>>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
#define ll long long 
#define scn(n) scanf("%d",&n)
#define lscn(n) scanf("%lld",&n)
#define lpri(n) printf("%lld",n)
#define pri(n) printf("%d",n)
#define pln() printf("\n")
#define priln(n) printf("%d\n",n)
#define lpriln(n) printf("%lld\n",n)
#define rep(i,init,n) for(int i=init;i<n;i++)
#define pb push_back     
#define mp make_pair
#define F first
#define S second
#define gcd __gcd
#define inf INT_MAX
#define ninf INT_MIN   
#define inf INT_MAX
#define linf LLONG_MAX
#define lninf LLONG_MIN   
const int mod = 1e9 + 7;
const int N = 2e5 + 4;

int solve()
{
	int n, m; scn(n); scn(m);

	set<pair<int, int>> as, bs;

	map<pair<int, int>, char> ma;

	while(m--)
	{
		cin >> ws;

		char type; cin >> type;

		if(type == '+')
		{
			int a, b; char ch; 

			scn(a); scn(b); cin >> ch;

			if(ma.find({b, a}) != ma.end())
			{
				as.emplace(a, b); as.emplace(b, a);

				if(ma[{b, a}] == ch)
				bs.emplace(a, b), bs.emplace(b, a);
			}

			ma[{a, b}] = ch;
		}
		else if(type == '-')
		{
			int a, b; scn(a); scn(b);

			char ch = ma[{a, b}];

			if(ma.find({b, a}) != ma.end())
			{
				as.erase({a, b}); as.erase({b, a});

				if(ma[{b, a}] == ch)
				bs.erase({b, a}), bs.erase({a, b});
			}

			ma.erase({a, b});
		}
		else
		{
			int k; scn(k);

			if(k & 1)
			{
				if((int)as.size() > 0)
				printf("YES\n");
				else
				printf("NO\n");
			}
			else
			{
				if((int)bs.size() > 0)
				printf("YES\n");
				else
				printf("NO\n");
			}
		}
	}

	return 0;
}

int main()                  
{
	int t = 1; //scn(t);

	while(t--)
	{
		solve();
	}

    return 0;
}