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

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcount

template<class T>
struct treap{
    struct node_t{
        T val; // 値
        node_t *lch, *rch;
        int pri; // 優先度
        int cnt; // 部分木のサイズ
        // T sum; // 部分木の値の和
        // T mn; // 部分木の最小値

        node_t(T v, int p):val(v), pri(p), cnt(1){
            lch = rch = NULL;
        }
    };

    const T INF = 19191919; // TODO:initialize
    mt19937 mt;
    node_t *root;
    treap():root(NULL){
        const int seed = 364364;
        mt = mt19937(seed);
    }

    int count(node_t *t){ return t ? t->cnt : 0; }
    // T sum(node_t *t){ return t ? t->sum : 0; }
    // T min(node_t *t){ return t ? t->mn : INF; }

    node_t *update(node_t *t){
        t->cnt = count(t->lch) + count(t->rch) + 1;
        // t->sum = sum(t->lch) + sum(t->rch) + t->val;
        // t->mn = std::min({min(t->lch), min(t->rch), t->val});
        return t;
    }

    node_t *merge(node_t *l, node_t *r){
        if(!l || !r) return l?l:r;

        if(l->pri > r->pri){ // 左の部分木の根のほうが優先度が高い
            l->rch = merge(l->rch, r);
            return update(l);
        }
        else{
            r->lch = merge(l, r->lch);
            return update(r);
        }
    }

    pair<node_t*, node_t*> split(node_t *t, int k){ // [0,k), [k,n)
        if(!t) return {NULL,NULL};
        if(k <= count(t->lch)){
            auto s = split(t->lch,k);
            t->lch = s.second;
            return {s.first, update(t)};
        }
        else{
            auto s = split(t->rch, k-count(t->lch)-1);
            t->rch = s.first;
            return {update(t), s.second};
        }
    }

    node_t *insert(node_t *t, int k, T val, int pri){
        auto s = split(t,k);
        t = merge(s.first, new node_t(val,pri));
        t = merge(t, s.second);
        return update(t);
    }

    node_t *erase(node_t *t, int k){
        auto s2 = split(t,k+1);
        auto s1 = split(s2.first, k);
        t = merge(s1.first, s2.second);
        return update(t);
    }

    node_t *find(node_t *t, int k){
        int c = count(t->lch);
        if(k < c) return find(t->lch,k);
        if(k == c) return t;
        return find(t->rch, k-c-1);
    }

    void insert(int k, T val){ root = insert(root, k, val, mt()); }
    void erase(int k){ root = erase(root, k); }
    node_t *find(int k){ return find(root,k); }

    // // circular shift (右端の値が左端に来て、それ以外が右に1つずつシフト)
    // void shift(int l, int r){
    //     if(r-l==1) return;
    //     assert(l<r);
    //     auto sr = split(root, r);
    //     auto sl = split(sr.first, l);
    //     auto lr = split(sl.second, r-l-1);
    //     root = merge(merge(sl.first, merge(lr.second, lr.first)), sr.second);
    // }

    // // [l,r)
    // T min(int l, int r){
    //     assert(l<r);
    //     auto sr = split(root, r);
    //     auto sl = split(sr.first, l);
    //     auto lr = sl.second;
    //     T ret = min(lr);
    //     // 元に戻す
    //     root = merge(merge(sl.first, lr), sr.second);
    //     return ret;
    // }
};

int N,Q;
vector<treap<int> > ts;

int main(){
  scanf("%d %d ",&N,&Q);
  ts.resize(N);
  rep(i,N){
    ts[i].insert(0,-1);
    int j=1;
    while(1){
      char c;
      scanf("%c",&c);
      if(c=='\n')break;
      ts[i].insert(j++,c-'a');
    }
  }

  while(Q--){
    int tp;
    scanf(" %d",&tp);
    if(tp==1){
      int a,b,c,d;
      scanf(" %d %d %d %d",&a,&b,&c,&d);
      a--;c--;

      auto pa=ts[a].split(ts[a].root,b);
      auto pc=ts[c].split(ts[c].root,d);

      ts[a].root=ts[a].merge(pa.fi,pc.se);
      ts[c].root=ts[c].merge(pc.fi,pa.se);
    }else{
      int a,b;
      char c;
      scanf(" %d %d %c",&a,&b,&c);
      a--;

      ts[a].erase(b);
      ts[a].insert(b,c-'a');
    }
  }

  rep(i,N){
    int sz=ts[i].count(ts[i].root);
    rep(j,sz-1)cout<<(char)(ts[i].find(j+1)->val+'a');
    cout<<endl;
  }
  return 0;
}



Measured memory_bytes: 148312