#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1005;
int N,Q,rod[maxn],vel[maxn];
bool moze[maxn][maxn];
vector<int> graf[maxn][30];
int getpar(int x){
   if(rod[x]==x)
      return x;
   rod[x]=getpar(rod[x]);
   return rod[x];
}
void dsuadd(int a,int b){
   a=getpar(a);
   b=getpar(b);
   if(a==b)
      return;
   if(vel[a]>vel[b])
      rod[b]=a;
   else{
      vel[b]=max(vel[a]+1,vel[b]);
      rod[a]=b;
   }
}
void spoj(int a,int b,int s);
void sviparovi(vector<int> &A,vector<int> &B,int s){
   if(moze[A[0]][B[0]]&(1<<s)) /// Vec smo ih spoili
      return;
   for(int x:A)
      for(int y:B)
         if(!moze[x][y])
            spoj(x,y,s);
}
void spoj(int a,int b,int s){
   if(moze[a][b])
      return;
   //cout<<"SPAJAM "<<a<<" "<<b<<endl;
   moze[a][b]|=(1<<s);
   moze[b][a]|=(1<<s);
   if(moze[a][b]!=(1<<s))
      return;
   for(int i=1;i<=26;i++){
      if(graf[a][i].size()==0)
         continue;
      if(graf[b][i].size()==0)
         continue;
      sviparovi(graf[b][i],graf[a][i],i);
   }
   return;
}
void dodaj(int a,int b,int s){ /// graf od a dodaje vezu ka b sa slovom s. To rezultuje da neki sa kojima b moze biti sada mogu i sa a, dok pre nisu mogli
   vector<int> A;
   A.push_back(a);
   for(int i=1;i<=N;i++){
      if(!moze[b][i])
         continue;
      if(graf[i][s].size()==0)
         continue;
      sviparovi(graf[i][s],A,s);
   }
}
void newedge(int a,int b,char x){
   x-='a'-1;
   graf[b][x].push_back(a);
   graf[a][x].push_back(b);
   dodaj(a,b,x);
   dodaj(b,a,x);
   for(int i=1;i<=26;i++)
      spoj(a,b,i);
}
struct upit{
   int t,a,b;
   char c;
}upiti[300005];
void solve(){
   bool case1=true;
   cin>>N>>Q;
   for(int i=1;i<=N;i++){
      rod[i]=i;
      vel[i]=1;
   }
   for(int i=1;i<=Q;i++){
      cin>>upiti[i].t>>upiti[i].a>>upiti[i].b;
      if(upiti[i].t==1){
         cin>>upiti[i].c;
         if(upiti[i].c!='a')
            case1=false;
      }
   }
   for(int i=1;i<=N;i++)
      moze[i][i]=(1<<27)-1;
   for(int q=1;q<=Q;q++){
      int t,a,b;
      char c;
      t=upiti[q].t;
      c=upiti[q].c;
      a=upiti[q].a;
      b=upiti[q].b;

      if(t==1){
         if(case1){
            dsuadd(a,b);
            continue;
         }
         newedge(a,b,c);
      }
      else
         if(case1)
            cout<<(getpar(a)==getpar(b))<<"\n";
         else
            if(moze[a][b])
               cout<<"1\n";
            else
               cout<<"0\n";
   }
}
void reset(){}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
        reset();
    }
    return 0;
}