#include<bits/stdc++.h>
#define START_LL 1
using namespace std;
#define start(x) using namespace x
#if START_LL
#define int long long
#endif
namespace IO{
inline int read(){
register int x=0,f=1;
register char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
return;
}
}start(IO);
const int N=6e6+5;
int q,len=0,pos=0;
char op[N],str[N];
namespace FHQ_Treap{
#define ls(p) Treap[p].l
#define rs(p) Treap[p].r
#define siz(p) Treap[p].siz
int rt,tot=0;
struct Node{ int l,r,siz,val,rnd; }Treap[N<<2];
void pushup(int p){ siz(p)=siz(ls(p))+siz(rs(p))+1; }
int NewNode(char x){
Treap[++tot]={0,0,1,x,rand()};
return tot;
}
void Split(int p,int x,int &l,int &r){
if(!p) return (void)(l=r=0);
if(siz(ls(p))+1<=x) Split(rs(l=p),x-siz(ls(p))-1,rs(p),r);
else Split(ls(r=p),x,l,ls(p));
pushup(p);
return ;
}
int Merge(int l,int r){
if(!l||!r) return l+r;
if(Treap[l].rnd<=Treap[r].rnd){
rs(l)=Merge(rs(l),r);
pushup(l);
return l;
}
ls(r)=Merge(l,ls(r));
pushup(r);
return r;
}
}start(FHQ_Treap);
signed main(){
q=read();
while(q--){
scanf("%s",op+1);
if(op[1]=='M') pos=read();
if(op[1]=='I'){
int x=read();
char ch;
while(x){
ch=getchar();
if(ch>=32&&ch<=126) --x,str[++len]=ch;
}
for(int i=1;i<=len;i++){
int pl,pr,px=NewNode(str[i]);
Split(rt,pos+i-1,pl,pr);
rt=Merge(pl,Merge(px,pr));
}
len=0;
}
if(op[1]=='D'){
int x=read(),pl,pr,px;
Split(rt,pos,pl,pr);
Split(pr,x,px,pr);
rt=Merge(pl,pr);
}
if(op[1]=='G'){
int x=read();
for(int i=pos+1;i<=pos+x;i++){
int pl,pr,px;
Split(rt,i-1,pl,pr);
Split(pr,1,px,pr);
putchar((char)(Treap[px].val));
rt=Merge(pl,Merge(px,pr));
}
putchar('\n');
}
if(op[1]=='P') --pos;
if(op[1]=='N') ++pos;
}
return 0;
}