Problem

There is a string $ S $ of length $ N $. All characters in $ S $ are numbers between 0 and 9.
When you make a sequence of $ \ frac {N \ times (N + 1)} {2} $, which is the number of terms created by enumerating all the numbers created from all the substrings of $ S $, Find the smallest value in $ H $.

Constraints

The input satisfies the following conditions.

* $ 1 \ leq N \ leq 10 ^ 5 $
* $ 1 \ leq H \ leq \ frac {N \ times (N + 1)} {2} $
* $ | S | = N $
* All characters in $ S $ are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

Input

The input is given in the following format.


$ N $ $ H $
$ S $


All inputs are given as integers.
$ N $ and $ H $ are given on the first line, separated by blanks.
The second line is given the string $ S $ of length $ N $.

Output

Output the $ H $ th value on one line.
(Do not include extra 0s at the beginning of the output.)

Examples

Input

2 3
00


Output

0


Input

4 9
0012


Output

12


Input

5 13
10031


Output

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

using ll=int64_t;
//#define int ll

#define FOR(i,a,b) for(int i=int(a);i<int(b);i++)
#define REP(i,b) FOR(i,0,b)
#define MP make_pair
#define PB push_back
#define ALL(x) x.begin(),x.end()
#ifdef MAROON_LOCAL
#define cerr (cerr<<"-- line "<<__LINE__<<" -- ")
#else
class CerrDummy{}cerrDummy;
template<class T>
CerrDummy& operator<<(CerrDummy&cd,const T&){
	return cd;
}
using charTDummy=char;
using traitsDummy=char_traits<charTDummy>;
CerrDummy& operator<<(CerrDummy&cd,basic_ostream<charTDummy,traitsDummy>&(basic_ostream<charTDummy,traitsDummy>&)){
	return cd;
}
#define cerr cerrDummy
#endif
#define REACH cerr<<"reached"<<endl
#define DMP(x) cerr<<#x<<":"<<x<<endl
#define ZERO(x) memset(x,0,sizeof(x))
#define ONE(x) memset(x,-1,sizeof(x))

using pi=pair<int,int>;
using vi=vector<int>;
using ld=long double;

template<class T,class U>
ostream& operator<<(ostream& os,const pair<T,U>& p){
	os<<"("<<p.first<<","<<p.second<<")";
	return os;
}

template<class T>
ostream& operator <<(ostream& os,const vector<T>& v){
	os<<"[";
	REP(i,(int)v.size()){
		if(i)os<<",";
		os<<v[i];
	}
	os<<"]";
	return os;
}

ll read(){
	ll i;
	scanf("%" SCNd64,&i);
	return i;
}

void printSpace(){
	printf(" ");
}

void printEoln(){
	printf("\n");
}

void print(ll x,int suc=1){
	printf("%" PRId64,x);
	if(suc==1)
		printEoln();
	if(suc==2)
		printSpace();
}

string readString(){
	static char buf[3341000];
	scanf("%s",buf);
	return string(buf);
}

char* readCharArray(){
	static char buf[3341000];
	static int bufUsed=0;
	char* ret=buf+bufUsed;
	scanf("%s",ret);
	bufUsed+=strlen(ret)+1;
	return ret;
}

template<class T,class U>
void chmax(T& a,U b){
	if(a<b)
		a=b;
}

template<class T,class U>
void chmin(T& a,U b){
	if(b<a)
		a=b;
}

template<class T>
T Sq(const T& t){
	return t*t;
}

#define CAPITAL
void Yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<endl;
	#else
	cout<<"Yes"<<endl;
	#endif
	if(ex)exit(0);
}
void No(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<endl;
	#else
	cout<<"No"<<endl;
	#endif
	if(ex)exit(0);
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif


const int Nmax=100010;
struct SuffixArray{
	vi sa,as,lcp;
};
namespace SA_IS{
	int bucket[Nmax];
	template <class T>
	void CreateBeginBucket(const T* data, int size, int maxVal){
		REP(i, maxVal + 1) bucket[i] = 0;
		REP(i, size) bucket[(int)data[i]]++;
		int sum = 0;
		REP(i, maxVal + 1){ bucket[i] += sum; swap(bucket[i], sum); }
	}
	 
	template <class T>
	void CreateEndBucket(const T* data, int size, int maxVal){
		REP(i, maxVal + 1) bucket[i] = 0;
		REP(i, size) bucket[(int)data[i]]++;
		int sum = 0;
		REP(i, maxVal + 1){ sum += bucket[i]; bucket[i] = sum; }
	}
	 
	template<class T>
	void InducedSort(const T* data, int size, int* SA, int maxVal, bool* isL){
		CreateBeginBucket(data, size, maxVal);
		REP(i, size) if (SA[i] > 0 && isL[SA[i] - 1]) SA[bucket[(int)data[SA[i] - 1]]++] = SA[i] - 1;
	}
	 
	template<class T>
	void InvertInducedSort(const T* data, int size, int* SA, int maxVal, bool* isL){
		CreateEndBucket(data, size, maxVal);
		for (int i = size - 1; i >= 0; --i) if (SA[i] > 0 && !isL[SA[i] - 1]) SA[--bucket[(int)data[SA[i] - 1]]] = SA[i] - 1;
	}
	 
	template <class T>
	void DBGOUT(const T* sa, int size){
		REP(i, size) printf("%d ", int(sa[i]));
		printf("\n");
	}
	 
	template<class T>
	void SA_IS(const T* data, int size, int* SA, int maxVal, bool* isL){
		REP(i, size) SA[i] = -1;
	#define isLMS(x) (x>0 && isL[x-1] && !isL[x])
		isL[size - 1] = false;
		for (int i = size - 2; i >= 0; i--) isL[i] = data[i] > data[i + 1] || (data[i] == data[i + 1] && isL[i + 1]);
		CreateEndBucket(data, size, maxVal);
		FOR(i, 1, size) if (isLMS(i)) SA[--bucket[(int)data[i]]] = i;
		InducedSort(data, size, SA, maxVal, isL);
		InvertInducedSort(data, size, SA, maxVal, isL);
	 
		int c = 0;
		REP(i, size) if (isLMS(SA[i])) SA[c++] = SA[i];
		FOR(i, c, size) SA[i] = -1;
	 
		int idx = -1;
		int prev = -1;
		REP(i, c){
			bool diff = false;
			REP(d, size){
				if (prev == -1 || data[SA[i] + d] != data[prev + d] || isL[SA[i] + d] != isL[prev + d]){
					diff = true;
					break;
				}
				else if (d > 0 && isLMS(SA[i] + d)) break;
			}
			if (diff){ idx++; prev = SA[i]; }
			SA[c + SA[i] / 2] = idx;
		}
		int j = size;
		for (int i = size - 1; i >= c; i--) if (SA[i] >= 0) SA[--j] = SA[i];
	 
		int* nxdata = SA + size - c;
		int* nxsa = SA;
		if (c == idx + 1) REP(i, c) nxsa[nxdata[i]] = i;
		else SA_IS(nxdata, c, nxsa, idx, isL + size);
	 
		j = c;
		for (int i = size - 1; i >= 1; i--) if (isLMS(i)) nxdata[--j] = i;
		REP(i, c) nxsa[i] = nxdata[nxsa[i]];
		FOR(i, c, size) SA[i] = -1;
		CreateEndBucket(data, size, maxVal);
		for (int i = c - 1; i >= 0; i--) swap(nxsa[i], SA[--bucket[(int)data[nxsa[i]]]]);
		InducedSort(data, size, SA, maxVal, isL);
		InvertInducedSort(data, size, SA, maxVal, isL);
	#undef isLMS
	}
	 
	bool isLPool[Nmax * 2];
	template<class T>
	void SA_IS(const T* data, int size, int* SA){
		int mv = 0;
		REP(i, size) if (mv < data[i]) mv = data[i];
		SA_IS(data, size, SA, mv, isLPool);
	}
	 
	int sa[Nmax],as[Nmax],lcp[Nmax];
	template<class T>
	void CreateLCP(const T* data, int size){
		REP(i,size) as[sa[i]]=i;
		int same=0;
		REP(i,size){
			if(as[i]<size-1){
				int j=sa[as[i]+1];
				while(i+same<size&&j+same<size&&data[i+same]==data[j+same])
					same++;
			}
			lcp[as[i]]=same;
			same=max(same-1,0);
		}
	}
	
	//last element should be 0(as a sentinel)
	//n is the length of the data(including the sentinel)
	template<class T>
	SuffixArray BuildSA(const T* data,int n){
		fill(bucket,bucket+n,0);
		fill(isLPool,isLPool+2*n,false);
		fill(sa,sa+n,0);
		fill(as,as+n,0);
		fill(lcp,lcp+n,0);
		SA_IS(data,n,sa);
		CreateLCP(data,n);
		return SuffixArray{vi(sa,sa+n),vi(as,as+n),vi(lcp,lcp+n)};
	}
}

ll CountZero(ll n,char*s){
	ll ans=0,len=0;
	REP(i,n)
		if(s[i]=='0'){
			ans+=(++len);
		}else{
			len=0;
		}
	return ans;
}

signed main(){
	ll n=read(),h=read();
	char* s=readCharArray();
	ll z=CountZero(n,s);
	if(h<=z){
		print(0);
		return 0;
	}
	h-=z;
	assert(h>0);
	vi w(n,1);
	REP(i,n-1)if(s[i]=='0')
		w[i+1]+=w[i];
	const auto Cnt=[&](ll mid){
		ll cnt=0;
		REP(i,n)if(s[i]!='0'){
			ll q=min(n-i,mid);
			cnt+=w[i]*q;
			cerr<<i<<" "<<w[i]<<endl;
		}
		return cnt;
	};
	ll bot=0,top=n;
	while((top-bot)>1){
		const ll mid=(bot+top)/2;
		ll cnt=Cnt(mid);
		cerr<<mid<<" "<<cnt<<endl;
		if(cnt<h){
			bot=mid;
		}else{
			top=mid;
		}
	}
	ll ansLen=top;
	h-=Cnt(ansLen-1);
	assert(h>0);
	auto SAIS=SA_IS::BuildSA(s,n+1);
	cerr<<ansLen<<endl;
	cerr<<h<<endl;
	cerr<<SAIS.sa<<endl;
	for(auto i:SAIS.sa){
		if(s[i]!='0'&&i+ansLen<=n){
			h-=w[i];
			if(h<=0){
				REP(j,ansLen)
					printf("%c",s[i+j]);
				printf("\n");
				return 0;
			}
		}
	}
	assert(false);
}

