#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <ctime>
#define _min(_a_,_b_) ((_a_)<(_b_)?(_a_):(_b_))
#define _max(_a_,_b_) ((_a_)>(_b_)?(_a_):(_b_))
template<class T>
inline T getnum()
{
register char c=0;
while(!(c>='0' && c<='9'))
c=getchar();
register T a=0;
while(c>='0' && c<='9')
{
a*=10,a+=c-'0';
c=getchar();
}
return a;
}
inline void getstr(int s[],int&lq)
{
lq=26;
register char c=0;
while(!((c>='a' && c<='z') || c=='?'))
c=getchar();
register int ls=0;
while((c>='a' && c<='z') || c=='?')
{
s[++ls]=c-'a'+1;
if(c=='?')
s[ls]=++lq;
c=getchar();
}
s[ls+1]=0;
return;
}
int uf[501010];
int UnionFind(register int x)
{
if(x == uf[x])
return x;
return uf[x]=UnionFind(uf[x]);
}
inline void UnionMerge(register int x,register int y)
{
register int fx=UnionFind(x),fy=UnionFind(y);
if(fx != fy)
uf[_max(fx,fy)]=_min(fx,fy);
}
int s[501010],os[501010];
int qval[501010];
unsigned _seed,_ret;
#define rnd() (_ret=_seed,_seed=_seed*7+23,_ret)
#pragma GCC optimize(3)
int root,cnt,size[501010],lson[501010],rson[501010],pri[501010];
bool rev[501010];
inline int CreateNode()
{
size[++cnt]=1;
pri[cnt]=rnd();
return cnt;
}
inline void PushUp(register int x)
{
size[x]=size[lson[x]]+size[rson[x]]+1;
}
inline void PushDown(register int x)
{
rev[x]^=1;
lson[x]^=rson[x]^=lson[x]^=rson[x];
rev[lson[x]]^=1,rev[rson[x]]^=1;
}
inline int MergeTree(register int x,register int y)
{
if(!x || !y)
return x^y;
if(rev[x])
PushDown(x);
if(rev[y])
PushDown(y);
if(pri[x] < pri[y])
{
rson[x]=MergeTree(rson[x],y);
return PushUp(x),x;
}
else
{
lson[y]=MergeTree(x,lson[y]);
return PushUp(y),y;
}
}
inline void SplitTreeByOrder(register int o,register int k,int&x,int&y)
{
if(!o)
{
x=y=0;
return;
}
if(rev[o])
PushDown(o);
if(k <= size[lson[o]])
y=o,SplitTreeByOrder(lson[o],k,x,lson[o]);
else
x=o,SplitTreeByOrder(rson[o],k-size[lson[o]]-1,rson[o],y);
PushUp(o);
}
inline int BuildTree(register int l,register int r)
{
static int stk[501010];
register int top=0;
for(register int i=l;i<=r;i++)
{
register int x=CreateNode(),last=0;
while(top && pri[stk[top]] > pri[x])
PushUp(stk[top]),last=stk[top],stk[top--]=0;
if(top)
rson[stk[top]]=x;
lson[x]=last,stk[++top]=x;
}
while(top)
PushUp(stk[top--]);
return stk[1];
}
int _tls;
void PrintTree(register int o)
{
if(rev[o])
PushDown(o);
if(lson[o])
PrintTree(lson[o]);
s[++_tls]=os[o];
if(rson[o])
PrintTree(rson[o]);
}
int main()
{
srand(time(NULL));_seed=(unsigned)rand()*rand();
register int N=getnum<int>(),M=getnum<int>();
long long K=getnum<long long>();
int lq=0;getstr(os,lq);
root=BuildTree(1,N);
for(register int i=1;i<=M;i++)
{
register int l=getnum<int>(),r=getnum<int>();
//for(register int j=l;j<r-j+l;j++)
// s[j]^=s[r-j+l]^=s[j]^=s[r-j+l];
int a,b,c,d;
SplitTreeByOrder(root,r,a,b);
SplitTreeByOrder(a,l-1,c,d);
rev[d]^=1;
root=MergeTree(c,MergeTree(d,b));
}
PrintTree(root);
for(register int i=26+1;i<=lq;i++)
uf[i]=i;
for(register int i=1;i<=N;i++)
if(os[i] != s[i])
{
if(os[i]>26 && s[i]>26)
UnionMerge(s[i],os[i]);
else
qval[(os[i]>26 ? os[i] : s[i])]=(os[i]>26 ? s[i] : os[i]);
}
for(register int i=26+1;i<=lq;i++)
if(qval[i])
qval[UnionFind(i)]=qval[i];
for(register int i=26+1;i<=lq;i++)
if(!qval[i])
qval[i]=qval[UnionFind(i)];
static int lst[501010];
register int lf=0;
for(register int i=26+1;i<=lq;i++)
if(i == UnionFind(i) && !qval[i])
lst[++lf]=i;
K--;
for(register int i=lf;i>=1;i--)
{
qval[lst[i]]=K%26+1;
K/=26;
}
for(register int i=26+1;i<=lq;i++)
if(!qval[i])
qval[i]=qval[UnionFind(i)];
for(register int i=1;i<=N;i++)
if(s[i] > 26)
putchar('a'+qval[s[i]]-1);
else
putchar('a'+s[i]-1);
putchar('\n');
return 0;
}