#include <bits/stdc++.h>
#define maxn 2020
#define pb push_back
#define debug
#define pii pair<int,int>
#define ppi pair<pii,int>
typedef long long ll;
using namespace std;

char mat[maxn][maxn];

int ord[maxn][maxn];
int dp[maxn][maxn];
int uu[maxn][maxn];

int main(){

    int n,k;
    scanf("%d%d",&n,&k);

    for(int i=0;i<n;i++)
        scanf(" %s",mat[i]);

    int best = -1;

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){

            dp[i][j] = 1e5;
            if(i == 0 && j == 0)
                dp[i][j] = (mat[i][j] != 'a');
            if(i)
                dp[i][j] = min(dp[i][j], dp[i-1][j] + (mat[i][j] != 'a'));
            if(j)
                dp[i][j] = min(dp[i][j], dp[i][j-1] + (mat[i][j] != 'a'));

            if(dp[i][j] <= k && i+j >= best)
                best = i + j;

        }

    for(int s = 2*n-2;s>=0;s--){

        vector<ppi> v;

        for(int i=0;i<n;i++){
            int j = s - i;
            if(j < 0 || j >= n) continue;
            int u = 1e4;
            if(i+1 < n) u = min(u,ord[i+1][j]);
            if(j+1 < n) u = min(u,ord[i][j+1]);
            uu[i][j] = u;
            v.pb(ppi(pii(mat[i][j],u),i));
        }

        sort(v.begin(),v.end());

        for(int i=0;i<v.size();i++){
            int x = v[i].second;
            int y = s - x;
            ord[x][y] = i;
        }

    }

    int rx = 0, ry = 0, q = 1e5;
    for(int i=0;i<=best;i++)
        printf("a");
    if(best == -1)
        printf("%c",mat[0][0]), best = 0;
    for(int x=0;x<n;x++){
        int y = best-x;
        if(y < 0 || y >= n) continue;
        if(dp[x][y] > k) continue;
        if(uu[x][y] < q){
            q = uu[x][y];
            rx = x, ry = y;
        }
    }

    while(rx + ry != 2*n-2){
        if(rx == n-1) ry++;
        else if(ry == n-1) rx++;
        else if(ord[rx+1][ry] < ord[rx][ry+1]) rx++;
        else ry++;
        printf("%c",mat[rx][ry]);
    }

}


#include <bits/stdc++.h>
#define maxn 2020
#define pb push_back
#define debug
#define pii pair<int,int>
#define ppi pair<pii,int>
typedef long long ll;
using namespace std;

char mat[maxn][maxn];

int ord[maxn][maxn];
int dp[maxn][maxn];

int main(){

    int n,k;
    scanf("%d%d",&n,&k);

    for(int i=0;i<n;i++)
        scanf(" %s",mat[i]);

    int best = -1;

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){

            dp[i][j] = 1e5;
            if(i == 0 && j == 0)
                dp[i][j] = (mat[i][j] != 'a');
            if(i)
                dp[i][j] = min(dp[i][j], dp[i-1][j] + (mat[i][j] != 'a'));
            if(j)
                dp[i][j] = min(dp[i][j], dp[i][j-1] + (mat[i][j] != 'a'));

            if(dp[i][j] <= k && i+j >= best)
                best = i + j;

        }

    for(int s = 2*n-2;s>=0;s--){

        vector<ppi> v;

        for(int i=0;i<n;i++){
            int j = s - i;
            if(j < 0 || j >= n) continue;
            int u = 1e5;
            if(i+1 < n) u = min(u,ord[i+1][j]);
            if(j+1 < n) u = min(u,ord[i][j+1]);
            v.pb(ppi(pii(mat[i][j],u),i));
        }

        sort(v.begin(),v.end());

        for(int i=0;i<v.size();i++){
            int x = v[i].second;
            int y = s - x;
            ord[x][y] = i;
        }

    }

    int rx = 0, ry = 0, q = 1e5;
    for(int i=0;i<=best;i++)
        printf("a");
    if(best == -1)
        printf("%c",mat[0][0]), best = 0;
    for(int x=0;x<n;x++){
        int y = best-x;
        if(y < 0 || y >= n) continue;
        if(dp[x][y] > k) continue;
        if(ord[x][y] < q){
            q = ord[x][y];
            rx = x, ry = y;
        }
    }

    while(rx + ry != 2*n-2){
        if(rx == n-1) ry++;
        else if(ry == n-1) rx++;
        else if(ord[rx+1][ry] < ord[rx][ry+1]) rx++;
        else ry++;
        printf("%c",mat[rx][ry]);
    }

}


#include <bits/stdc++.h>
#define maxn 2020
#define pb push_back
#define debug
#define pii pair<int,int>
#define ppi pair<pii,int>
typedef long long ll;
using namespace std;

char mat[maxn][maxn];

int ord[maxn][maxn];
int dp[maxn][maxn];

int main(){

    int n,k;
    scanf("%d%d",&n,&k);

    for(int i=0;i<n;i++)
        scanf(" %s",mat[i]);

    int best = -1;

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){

            dp[i][j] = 1e5;
            if(i == 0 && j == 0)
                dp[i][j] = (mat[i][j] != 'a');
            if(i)
                dp[i][j] = min(dp[i][j], dp[i-1][j] + (mat[i][j] != 'a'));
            if(j)
                dp[i][j] = min(dp[i][j], dp[i][j-1] + (mat[i][j] != 'a'));

            if(dp[i][j] <= k && i+j >= best)
                best = i + j;

        }

    for(int s = 2*n-2;s>=0;s--){

        vector<ppi> v;

        for(int i=0;i<n;i++){
            int j = s - i;
            if(j < 0 || j >= n) continue;
            int u = 1e5;
            if(i+1 < n) u = min(u,ord[i+1][j]);
            if(j+1 < n) u = min(u,ord[i][j+1]);
            v.pb(ppi(pii(mat[i][j],u),i));
        }

        sort(v.begin(),v.end());

        for(int i=0;i<v.size();i++){
            int x = v[i].second;
            int y = s - x;
            ord[x][y] = i;
        }

    }

    int rx, ry, q = 1e5;
    for(int i=0;i<=best;i++)
        printf("a");
    if(best == -1)
        printf("%c",mat[0][0]), best = 0;
    for(int x=0;x<n;x++){
        int y = best-x;
        if(y < 0 || y >= n) continue;
        if(ord[x][y] < q){
            q = ord[x][y];
            rx = x, ry = y;
        }
    }

    while(rx + ry != 2*n-2){
        if(rx == n-1) ry++;
        else if(ry == n-1) rx++;
        else if(ord[rx+1][ry] < ord[rx][ry+1]) rx++;
        else ry++;
        printf("%c",mat[rx][ry]);
    }

}


#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#define ll          long long
#define pb          push_back
#define mp          make_pair
#define pii         pair<int,int>
#define vi          vector<int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (int)x.size()
#define hell        1000000007
#define endl        '\n'
#define rep(i,a,b)  for(int i=a;i<b;i++)
using namespace std;

string to_string(string s) {
	return '"' + s + '"';
}

string to_string(const char* s) {
	return to_string((string) s);
}

string to_string(bool b) {
	return (b ? "true" : "false");
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A>
string to_string(A v) {
	bool first = true;
	string res = "{";
	for (const auto &x : v) {
		if (!first) {
			res += ", ";
		}
		first = false;
		res += to_string(x);
	}
	res += "}";
	return res;
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

#ifdef PRINTERS
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

string s[2000];
int dp[2005][2005];
#define move fuck
int move[2005][2005];
void solve(){
	int n,k;
	cin>>n>>k;
	rep(i,0,n)cin>>s[i];
	int best=-1;
	rep(i,0,n){
		rep(j,0,n){
			if(i==0 and j==0)dp[i][j]=(s[i][j]!='a');
			else if(i==0)dp[i][j]=(s[i][j]!='a')+dp[i][j-1];
			else if(j==0)dp[i][j]=(s[i][j]!='a')+dp[i-1][j];
			else dp[i][j]=(s[i][j]!='a')+min(dp[i-1][j],dp[i][j-1]);
			if(dp[i][j]<=k)best=max(best,i+j);
		}
	}
	for(int i=2*n-3;i>=0;i--){
		vector<pii>temp;
		rep(j,0,n){
			if(i-j<n and i-j>=0)temp.pb(mp(j,i-j));
		}
		auto f=[&](pii a){return min(a.F+1<n?move[a.F+1][a.S]:INT_MAX,a.S+1<n?move[a.F][a.S+1]:INT_MAX);};
		sort(all(temp),[&](pii a,pii b){
			if(s[a.F][a.S]==s[b.F][b.S])return f(a)<f(b);
			return s[a.F][a.S]<s[b.F][b.S];
		});
		rep(j,0,sz(temp))move[temp[j].F][temp[j].S]=j;
	}
	string res=string(best+1,'a');
	if(sz(res)==2*n-1){
		cout<<res<<endl;
		return;
	}
	debug(res);
	int zeta=-1;
	rep(j,0,n){
		if(best+1-j<n and best+1-j>=0 and ((j>0 and dp[j-1][best+1-j]==k) or (best-j>=0 and dp[j][best-j]==k))){
			debug(j,best+1-j);
			if(zeta==-1 or move[zeta][best+1-zeta]>move[j][best+1-j])zeta=j;
		}
	}
	zeta=max(zeta,0);
	cerr<<zeta<<endl;
	rep(_,best+1,2*n-1){
		res.pb(s[zeta][_-zeta]);
		if(zeta==n-1);
		else if(_-zeta==n-1)zeta++;
		else if(move[zeta+1][_-zeta]<move[zeta][_-zeta+1])zeta++;
		else{}
	}
	cout<<res;
}

#undef move
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}


#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#define ll          long long
#define pb          push_back
#define mp          make_pair
#define pii         pair<int,int>
#define vi          vector<int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (int)x.size()
#define hell        1000000007
#define endl        '\n'
#define rep(i,a,b)  for(int i=a;i<b;i++)
using namespace std;

string to_string(string s) {
	return '"' + s + '"';
}

string to_string(const char* s) {
	return to_string((string) s);
}

string to_string(bool b) {
	return (b ? "true" : "false");
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A>
string to_string(A v) {
	bool first = true;
	string res = "{";
	for (const auto &x : v) {
		if (!first) {
			res += ", ";
		}
		first = false;
		res += to_string(x);
	}
	res += "}";
	return res;
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

#ifdef PRINTERS
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

string s[2000];
int dp[2005][2005];
bool good[2005][2005];
void solve(){
	int n,k;
	cin>>n>>k;
	rep(i,0,n)cin>>s[i];
	int best=1;
	rep(i,1,n+1){
		rep(j,1,n+1){
			if(i==1 and j==1)dp[i][j]=(s[i-1][j-1]!='a');
			else if(i==1)dp[i][j]=(s[i-1][j-1]!='a')+dp[i][j-1];
			else if(j==1)dp[i][j]=(s[i-1][j-1]!='a')+dp[i-1][j];
			else dp[i][j]=(s[i-1][j-1]!='a')+min(dp[i-1][j],dp[i][j-1]);
			if(dp[i][j]<=k)best=max(best,i+j);
		}
	}
	string res=string(best-1,'a');
	vector<pii> alpha;
	for(int i=1;i<=n;i++){
		if(best+1-i<=n and best+1-i>=1 and (dp[i-1][best+1-i]<=k or dp[i][best-i]<=k))alpha.pb(mp(i,best+1-i));
	}
	debug(res,best,alpha);
	for(int sum=best+1;sum<=2*n;sum++){
		sort(all(alpha),[&](pii a,pii b){return s[a.F-1][a.S-1]<s[b.F-1][b.S-1];});
		set<pii>zeta;
		for(auto& i:alpha){
			if(s[i.F-1][i.S-1]==s[alpha[0].F-1][alpha[0].S-1]){
				good[i.F][i.S]=1;
				if(i.F+1<=n){
					zeta.insert(mp(i.F+1,i.S));
				}
				if(i.S+1<=n){
					zeta.insert(mp(i.F,i.S+1));
				}
			}
		}
		alpha=vector<pii>(all(zeta));
	}
	string res2;
	pii cur=mp(n,n);
	while(good[cur.F][cur.S]){
		res2.pb(s[cur.F-1][cur.S-1]);
		if(cur.F>1 and good[cur.F-1][cur.S])cur.F--;
		else if(cur.S>1 and good[cur.F][cur.S-1])cur.S--;
		else break;
	}
	reverse(all(res2));
	cout<<res<<res2;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}


#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#define ll          long long
#define pb          push_back
#define mp          make_pair
#define pii         pair<int,int>
#define vi          vector<int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (int)x.size()
#define hell        1000000007
#define endl        '\n'
#define rep(i,a,b)  for(int i=a;i<b;i++)
using namespace std;

string to_string(string s) {
	return '"' + s + '"';
}

string to_string(const char* s) {
	return to_string((string) s);
}

string to_string(bool b) {
	return (b ? "true" : "false");
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A>
string to_string(A v) {
	bool first = true;
	string res = "{";
	for (const auto &x : v) {
		if (!first) {
			res += ", ";
		}
		first = false;
		res += to_string(x);
	}
	res += "}";
	return res;
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

#ifdef PRINTERS
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

string s[2000];
int dp[2005][2005];
#define move fuck
int move[2005][2005];
void solve(){
	int n,k;
	cin>>n>>k;
	rep(i,0,n)cin>>s[i];
	int best=-1;
	rep(i,0,n){
		rep(j,0,n){
			if(i==0 and j==0)dp[i][j]=(s[i][j]!='a');
			else if(i==0)dp[i][j]=(s[i][j]!='a')+dp[i][j-1];
			else if(j==0)dp[i][j]=(s[i][j]!='a')+dp[i-1][j];
			else dp[i][j]=(s[i][j]!='a')+min(dp[i-1][j],dp[i][j-1]);
			if(dp[i][j]<=k)best=max(best,i+j);
		}
	}
	for(int i=2*n-3;i>=0;i--){
		vector<pii>temp;
		rep(j,0,n){
			if(i-j<n and i-j>=0)temp.pb(mp(j,i-j));
		}
		auto f=[&](pii a){return min(a.F+1<n?move[a.F+1][a.S]:INT_MAX,a.S+1<n?move[a.F][a.S+1]:INT_MAX);};
		sort(all(temp),[&](pii a,pii b){
			if(s[a.F][a.S]==s[b.F][b.S])return f(a)<f(b);
			return s[a.F][a.S]<s[b.F][b.S];
		});
		rep(j,0,sz(temp))move[temp[j].F][temp[j].S]=j;
	}
	string res=string(best+1,'a');
	if(sz(res)==2*n-1){
		cout<<res<<endl;
		return;
	}
	debug(res);
	int zeta=0;
	rep(j,0,n){
		if(best+1-j<n and best+1-j>=0 and ((j>0 and dp[j-1][best+1-j]==k) or (best-j>=0 and dp[j][best-j]==k))){
			debug(j,best+1-j);
			if(zeta==-1 or move[zeta][best+1-zeta]>move[j][best+1-j])zeta=j;
		}
	}
	rep(_,best+1,2*n-1){
		res.pb(s[zeta][_-zeta]);
		if(zeta==n-1);
		else if(_-zeta==n-1)zeta++;
		else if(move[zeta+1][_-zeta]<move[zeta][_-zeta+1])zeta++;
		else{}
	}
	cout<<res;
}

#undef move
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <climits>
#include <set>
#include <bitset>
#include <math.h>
#include <queue>
#include <map>
#include <sstream>
#include <functional>
#include <assert.h>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <regex>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
template <typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T> using max_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;

#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
#define FOR(i, start, end) for(int i = (start); i < (end); i++)
#define ROF(i, start, end) for(int i = (start); i >= (end); i--)
#define all(x) (x).begin(), (x).end()
//#define endl "\n"
#define PI (asin(1)*2)
#define oo 1000000000LL
#define OO 1000000000000000000LL
#define eps 1e-8
#define in(a, b)   ((b).find(a) != (b).end())
#define mp(a, b)   make_pair((a), (b))
#define sgn(a)     ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
#define cl1(x)     ((x)&((x)-1)) // clear lowest 1 bit
#define cl0(x)     ((x)|((x)+1)) // clear lowest 0 bit
#define ct1(x)     ((x)&((x)+1)) // clear all trailing 1 bits
#define pb push_back
#define MOD 1000000007
#define MAX_N 100000
using namespace std;

char brd[2000][2000];
int dist[2000][2000];

int main()
{
    FAST_IO
#ifdef _DEBUG
        freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n, k;
    cin >> n >> k;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            cin >> brd[i][j];
            dist[i][j] = oo;
        }
    }
    int maxPrefLen = -1;
    dist[0][0] = 0;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (i - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i - 1][j]);
            }
            if (j - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i][j - 1]);
            }
            if (brd[i][j] != 'a') {
                dist[i][j]++;
            }
            if(dist[i][j] <= k) maxPrefLen = max(maxPrefLen, i + j);
        }
    }
    FOR(_, 0, maxPrefLen + 1) {
        cout << 'a';
    }
    vector<pii> curr;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (dist[i][j] <= k && i + j == maxPrefLen) {
                curr.pb({ i,j });
            }
        }
    }
    if (curr.size() == 0) {
        curr.pb({ 0,0 });
    }
    while (curr.size() > 0) {
        char smol = 'z'+1;
        vector<pii> nxt;
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n) {
                smol = min(smol, brd[i + 1][j]);
            }
            if (j + 1 < n) {
                smol = min(smol, brd[i][j + 1]);
            }
        }
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n && smol == brd[i+1][j]) {
                nxt.pb({ i + 1,j });
            }
            if (j + 1 < n && smol == brd[i][j+1]) {
                nxt.pb({ i,j + 1 });
            }
        }
        if (nxt.size() == 0) break;
        cout << smol;
        curr = nxt;
    }
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <climits>
#include <set>
#include <bitset>
#include <math.h>
#include <queue>
#include <map>
#include <sstream>
#include <functional>
#include <assert.h>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <regex>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
template <typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T> using max_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;

#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
#define FOR(i, start, end) for(int i = (start); i < (end); i++)
#define ROF(i, start, end) for(int i = (start); i >= (end); i--)
#define all(x) (x).begin(), (x).end()
//#define endl "\n"
#define PI (asin(1)*2)
#define oo 1000000000LL
#define OO 1000000000000000000LL
#define eps 1e-8
#define in(a, b)   ((b).find(a) != (b).end())
#define mp(a, b)   make_pair((a), (b))
#define sgn(a)     ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
#define cl1(x)     ((x)&((x)-1)) // clear lowest 1 bit
#define cl0(x)     ((x)|((x)+1)) // clear lowest 0 bit
#define ct1(x)     ((x)&((x)+1)) // clear all trailing 1 bits
#define pb push_back
#define MOD 1000000007
#define MAX_N 100000
using namespace std;

char brd[2000][2000];
int dist[2000][2000];

int main()
{
    FAST_IO
#ifdef _DEBUG
        freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n, k;
    cin >> n >> k;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            cin >> brd[i][j];
            dist[i][j] = oo;
        }
    }
    int maxPrefLen = -1;
    dist[0][0] = 0;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (i - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i - 1][j]);
            }
            if (j - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i][j - 1]);
            }
            if (brd[i][j] != 'a') {
                dist[i][j]++;
            }
            if(dist[i][j] <= k) maxPrefLen = max(maxPrefLen, i + j);
        }
    }
    FOR(_, 0, maxPrefLen + 1) {
        cout << 'a';
    }
    vector<pii> curr;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (dist[i][j] <= k && i + j == maxPrefLen) {
                curr.pb({ i,j });
            }
        }
    }
    bool print = false;
    if (curr.size() == 0) {
        curr.pb({ 0,0 });
        print = true;
    }
    while (curr.size() > 0) {
        if (print) cout << brd[curr[0].first][curr[0].second];
        print = true;
        char smol = 'z'+1;
        vector<pii> nxt;
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n) {
                smol = min(smol, brd[i + 1][j]);
            }
            if (j + 1 < n) {
                smol = min(smol, brd[i][j + 1]);
            }
        }
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n && smol == brd[i+1][j]) {
                nxt.pb({ i + 1,j });
            }
            if (j + 1 < n && smol == brd[i][j+1]) {
                nxt.pb({ i,j + 1 });
            }
        }
        curr = nxt;
    }
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <climits>
#include <set>
#include <bitset>
#include <math.h>
#include <queue>
#include <map>
#include <sstream>
#include <functional>
#include <assert.h>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <regex>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
template <typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T> using max_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;

#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
#define FOR(i, start, end) for(int i = (start); i < (end); i++)
#define ROF(i, start, end) for(int i = (start); i >= (end); i--)
#define all(x) (x).begin(), (x).end()
//#define endl "\n"
#define PI (asin(1)*2)
#define oo 1000000000LL
#define OO 1000000000000000000LL
#define eps 1e-8
#define in(a, b)   ((b).find(a) != (b).end())
#define mp(a, b)   make_pair((a), (b))
#define sgn(a)     ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
#define cl1(x)     ((x)&((x)-1)) // clear lowest 1 bit
#define cl0(x)     ((x)|((x)+1)) // clear lowest 0 bit
#define ct1(x)     ((x)&((x)+1)) // clear all trailing 1 bits
#define pb push_back
#define MOD 1000000007
#define MAX_N 100000
using namespace std;

char brd[2000][2000];
int dist[2000][2000];

int main()
{
    FAST_IO
#ifdef _DEBUG
        freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n, k;
    cin >> n >> k;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            cin >> brd[i][j];
            dist[i][j] = oo;
        }
    }
    int maxPrefLen = -1;
    dist[0][0] = 0;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (i - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i - 1][j]);
            }
            if (j - 1 >= 0) {
                dist[i][j] = min(dist[i][j], dist[i][j - 1]);
            }
            if (brd[i][j] != 'a') {
                dist[i][j]++;
            }
            if(dist[i][j] <= k) maxPrefLen = max(maxPrefLen, i + j);
        }
    }
    FOR(_, 0, maxPrefLen + 1) {
        cout << 'a';
    }
    set<pii> curr;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            if (dist[i][j] <= k && i + j == maxPrefLen) {
                curr.insert({ i,j });
            }
        }
    }
    bool print = false;
    if (curr.size() == 0) {
        curr.insert({ 0,0 });
        print = true;
    }
    while (curr.size() > 0) {
        auto it = *curr.begin();
        if (print) cout << brd[it.first][it.second];
        print = true;
        char smol = 'z'+1;
        set<pii> nxt;
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n) {
                smol = min(smol, brd[i + 1][j]);
            }
            if (j + 1 < n) {
                smol = min(smol, brd[i][j + 1]);
            }
        }
        for (auto x : curr) {
            int i = x.first;
            int j = x.second;
            if (i + 1 < n && smol == brd[i+1][j]) {
                nxt.insert({ i + 1,j });
            }
            if (j + 1 < n && smol == brd[i][j+1]) {
                nxt.insert({ i,j + 1 });
            }
        }
        curr = nxt;
    }
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <climits>
#include <set>
#include <bitset>
#include <math.h>
#include <queue>
#include <map>
#include <sstream>
#include <functional>
#include <assert.h>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <random>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
template <typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T> using max_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;

#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
#define FOR(i, start, end) for(int i = (start); i < (end); i++)
#define ROF(i, start, end) for(int i = (start); i >= (end); i--)
#define all(x) (x).begin(), (x).end()
//#define endl "\n"
#define oo ((1LL<<31)-1)
#define OO ((1LL<<63)-1)
#define eps 1e-12
#define in(a, b)   ((b).find(a) != (b).end())
#define mp(a, b)   make_pair((a), (b))
#define sgn(a)     ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
#define cl1(x)     ((x)&((x)-1)) // clear lowest 1 bit
#define cl0(x)     ((x)|((x)+1)) // clear lowest 0 bit
#define ct1(x)     ((x)&((x)+1)) // clear all trailing 1 bits
#define pb push_back
#define MOD 1000000007
#define MAX_N 2000
const ld PI = asin(1) * 2;
using namespace std;

char brd[MAX_N][MAX_N];
//vector<char> minLetters[MAX_N][MAX_N];
//vector<pii> prev[MAX_N][MAX_N];

map<pair<pii, int>, string> dp;
int n, k;

string min(string a, string b) {
    if (a == "") return b;
    if (b == "") return a;
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    bool isA = a < b;
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    return isA ? a : b;
}

string f(int i, int j, int k) {
    if (i >= n || j >= n) {
        return "";
    }
    if (k < 0) {
        return "";
    }
    pair<pii, int> input = { {i,j},k };
    if (dp.find(input) != dp.end()) return dp[input];

    string res;
    if (brd[i][j] == 'a') {
        // already have an a, don't try to change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        res = min(noDown, noRight);
        res.pb('a');
    }
    else if (k > 0) {
        // not an a, but we can change - do that
        auto yesDown = f(i + 1, j, k - 1);
        auto yesRight = f(i, j + 1, k - 1);
        res = min(yesDown, yesRight);
        res.pb('a');

        // or don't change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        string res2 = min(noDown, noRight);
        res2.pb(brd[i][j]);
        res = min(res, res2);
    }
    else {
        // not an a and we can't change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        res = min(noDown, noRight);
        res.pb(brd[i][j]);
    }

    return dp[input] = res;
}

int main()
{
    FAST_IO
#ifdef _DEBUG
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    cin >> n >> k;
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            cin >> brd[i][j];
        }
    }
    string res = f(0, 0, k);
    reverse(res.begin(), res.end());
    cout << res;
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <climits>
#include <set>
#include <bitset>
#include <math.h>
#include <queue>
#include <map>
#include <sstream>
#include <functional>
#include <assert.h>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <random>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<double, double> pdd;
template <typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T> using max_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;

#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
#define FOR(i, start, end) for(int i = (start); i < (end); i++)
#define ROF(i, start, end) for(int i = (start); i >= (end); i--)
#define all(x) (x).begin(), (x).end()
//#define endl "\n"
#define oo ((1LL<<31)-1)
#define OO ((1LL<<63)-1)
#define eps 1e-12
#define in(a, b)   ((b).find(a) != (b).end())
#define mp(a, b)   make_pair((a), (b))
#define sgn(a)     ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
#define cl1(x)     ((x)&((x)-1)) // clear lowest 1 bit
#define cl0(x)     ((x)|((x)+1)) // clear lowest 0 bit
#define ct1(x)     ((x)&((x)+1)) // clear all trailing 1 bits
#define pb push_back
#define MOD 1000000007
#define MAX_N 2000
const ld PI = asin(1) * 2;
using namespace std;

ll A1 = 999999937, B1 = 1000000009, A2 = 1000000033, B2 = 1000000097;

ll pwr(ll a, int e, ll m) {
    if (e == 0) return 1;
    ll half = pwr(a, e / 2, m);
    half *= half;
    if (e % 2 == 1) half *= a;
    return half % m;
}

struct GoodString {
    string s;
    deque<pii> h;

    void append(char c) {
        string ss = "";
        ss += c;
        ss += s;
        s = ss;
        // ^ tmp
        /*pii prev;
        if (h.size() == 0) {
            prev = { 0,0 };
        }
        else {
            prev = h.front();
        }

        pii newH = {
            (pwr(A1,h.size(),B1)*c + prev.first) % B1,
            (pwr(A2,h.size(),B2)*c + prev.second) % B2
        };
        h.push_front(newH);*/
        pii curr = { c, c };
        h.push_front(curr);
        FOR(i, 0, s.length()) {
            h[i] = curr;
            curr.first = (A1*curr.first + s[i]) % B1;
            curr.second = (A2*curr.second + s[i]) % B2;
        }
    }

    bool operator<(const GoodString& b) const {
        if (s == "") return false;
        if (b.s == "") return true;
        int mxLen = min(s.length(), b.s.length());
        int loLen = 1, hiLen = mxLen;
        while (loLen < hiLen) {
            int len = (loLen + hiLen + 1) / 2;
            int ja = len-1;
            int jb = len - 1;
            pii ha = h[ja];
            pii hb = b.h[jb];
            if (ha == hb) {
                loLen = len;
            }
            else {
                hiLen = len - 1;
            }
        }
        int ja = loLen-1;
            int jb = loLen-1;

        // ??
        if (ja <0||jb<0) {
            return false;
        }
        return s[ja] < b.s[jb];
    }

    string toStr() {
        string t = s;
        return t;
    }
};

GoodString emptyStr() {
    GoodString gs;
    gs.s = "";
    gs.h = {};
    return gs;
}

char brd[MAX_N][MAX_N];
//vector<char> minLetters[MAX_N][MAX_N];
//vector<pii> prev[MAX_N][MAX_N];

map<pair<pii, int>, GoodString> dp;
int n, k;

GoodString min(GoodString a, GoodString b) {
    return a < b ? a : b;
}

GoodString f(int i, int j, int k) {
    if (i >= n || j >= n) {
        return emptyStr();
    }
    if (k < 0) {
        return emptyStr();
    }
    pair<pii, int> input = { {i,j},k };
    if (dp.find(input) != dp.end()) return dp[input];

    GoodString res;
    if (brd[i][j] == 'a') {
        // already have an a, don't try to change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        res = min(noDown, noRight);
        res.append('a');
    }
    else if (k > 0) {
        // not an a, but we can change - do that
        auto yesDown = f(i + 1, j, k - 1);
        auto yesRight = f(i, j + 1, k - 1);
        res = min(yesDown, yesRight);
        res.append('a');

        // or don't change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        GoodString res2 = min(noDown, noRight);
        res2.append(brd[i][j]);
        res = min(res, res2);
    }
    else {
        // not an a and we can't change
        auto noDown = f(i + 1, j, k);
        auto noRight = f(i, j + 1, k);
        res = min(noDown, noRight);
        res.append(brd[i][j]);
    }

    return dp[input] = res;
}

bool isPrime(ll x) {
    for (ll i = 2; i*i <= x; i++) {
        if (x%i == 0)return false;
    }
    return true;
}

int main()
{
    FAST_IO
#ifdef _DEBUG
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    cin >> n >> k;
    k = min(k, 2 * n - 1);
    FOR(i, 0, n) {
        FOR(j, 0, n) {
            cin >> brd[i][j];
        }
    }
    GoodString res = f(0, 0, k);
    cout << res.toStr();
    /*FOR(i, 1000000000 - 100, 1000000000 + 100) {
        if (isPrime(i)) {
            cout << i << endl;
        }
    }*/
    return 0;
}


#include<bits/stdc++.h>
#define N 2001
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int sz[N];
int lenx[N+N][N],leny[N+N][N],vis[N][N];
int n,k;
vector< string > ar(N);
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    lenx[0][0] = 0; leny[0][0] = 0;
    ans[0] = ar[0][0];
    sz[0] = 1;
    for(int i=0;i<n+n-1;i++){
        for(int k = 0;k<sz[i];k++){
            int x = lenx[i][k]; int y = leny[i][k];
            if(check(x+1,y)&&!vis[x+1][y]){
              if(ar[x+1][y]==ans[i+1]){
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  vis[x+1][y] = 1;
              }
              else if(ar[x+1][y]<ans[i+1]) {
                  sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  ans[i+1] = ar[x+1][y];
                  vis[x+1][y] = 1;
              }
            }
            if(check(x,y+1)&&!vis[x][y+1]){
                vis[x][y+1] = 1;
              if(ar[x][y+1]==ans[i+1])  {
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y+1 ;
              }
              else if(ar[x][y+1]<ans[i+1]) {
                 sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y +1;
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }


#include<bits/stdc++.h>
#define N 2005
#define int long long
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
vector< vector< pair< int ,int > > >  len(N+N);
int n,k;
vector< string > ar;
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    ar.resize(n);
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    len[0].pb({0,0});
    ans[0] = ar[0][0];
    for(int i=0;i<n+n-1;i++){
        for(auto j: len[i]){
            int x = j.x; int y = j.y;
            if(check(x+1,y)){
              if(ar[x+1][y]==ans[i+1])  len[i+1].pb({x+1,y});
              else if(ar[x+1][y]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x+1,y});
                  ans[i+1] = ar[x+1][y];
              }
            }
            if(check(x,y+1)){
              if(ar[x][y+1]==ans[i+1])  len[i+1].pb({x,y+1});
              else if(ar[x][y+1]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x,y+1});
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2005
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int nu[N][N];
int vis[N][N];
vector< vector< pair< int ,int > > >  len(N+N);

queue< pair< int , int >>q;
int n,k;
vector< string > ar;
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    ar.resize(n);

    for(int i=0;i<N+N;i++)
        ans[i] = 'z'+1;
    for(int i=0;i<n;i++)
        cin>>ar[i];
    q.push({0,0});
    nu[0][0] = k;
    vis[0][0] = 1;
   while(!q.empty()){
       int x = q.front().x; int y= q.front().y;
       q.pop();
     //  cout<<x<<" "<<y<<" "<<nu[x][y]<<"\n";
       if(nu[x][y]&&ar[x][y]!='a'){
           ar[x][y] = 'a';
           nu[x][y]--;
       }
       if(check(x+1,y)){
           if(nu[x+1][y]<nu[x][y]){
               nu[x+1][y] = nu[x][y];
           }
           if(!vis[x+1][y]){
               vis[x+1][y] = 1;
               q.push({x+1,y});
           }
       }
        if(check(x,y+1)){
           if(nu[x][y+1]<nu[x][y]){
               nu[x][y+1] = nu[x][y];
           }
           if(!vis[x][y+1]){
               vis[x][y+1] = 1;
               q.push({x,y+1});
           }
       }
   }
   memset(vis,0,sizeof(vis));
   len[0].pb({0,0});
    ans[0] = ar[0][0];
    for(int i=0;i<n+n-1;i++){
        for(auto j: len[i]){
            int x = j.x; int y = j.y;
            if(check(x+1,y)&&!vis[x+1][y]){
                vis[x+1][y] = 1;
              if(ar[x+1][y]==ans[i+1])  len[i+1].pb({x+1,y});
              else if(ar[x+1][y]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x+1,y});
                  ans[i+1] = ar[x+1][y];
              }
            }
            if(check(x,y+1)&&!vis[x][y+1]){
                vis[x][y+1] = 1;
              if(ar[x][y+1]==ans[i+1])  len[i+1].pb({x,y+1});
              else if(ar[x][y+1]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x,y+1});
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
    }
   /* for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
          //  cout<<nu[i][j];
          //  cout<<"\n";

    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
            cout<<ar[i][j];
            cout<<"\n";
    }*/
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2001
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int sz[N];
int lenx[N+N][N],leny[N+N][N];
int n,k;
vector< string > ar(N);
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    lenx[0][0] = 0; leny[0][0] = 0;
    ans[0] = ar[0][0];
    sz[0] = 1;
    for(int i=0;i<n+n-1;i++){
        for(int k = 0;k<sz[i];k++){
            int x = lenx[i][k]; int y = leny[i][k];
            if(check(x+1,y)){
              if(ar[x+1][y]==ans[i+1]){
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
              }
              else if(ar[x+1][y]<ans[i+1]) {
                  sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  ans[i+1] = ar[x+1][y];
              }
            }
            if(check(x,y+1)){
              if(ar[x][y+1]==ans[i+1])  {
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y+1 ;
              }
              else if(ar[x][y+1]<ans[i+1]) {
                 sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y +1;
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2001
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int sz[N];
int lenx[N+N][N],leny[N+N][N],vis[N][N];
int n,k;
vector< string > ar(N);
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    lenx[0][0] = 0; leny[0][0] = 0;
    ans[0] = ar[0][0];
    sz[0] = 1;
    for(int i=0;i<n+n-1;i++){
        for(int k = 0;k<sz[i];k++){
            int x = lenx[i][k]; int y = leny[i][k];
            if(check(x+1,y)&&!vis[x+1][y]){
              if(ar[x+1][y]==ans[i+1]){
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  vis[x+1][y] = 1;
              }
              else if(ar[x+1][y]<ans[i+1]) {
                  sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  ans[i+1] = ar[x+1][y];
                  vis[x+1][y] = 1;
              }
            }
            if(check(x,y+1)&&!vis[x][y+1]){
                vis[x][y+1] = 1;
              if(ar[x][y+1]==ans[i+1])  {
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y+1 ;
              }
              else if(ar[x][y+1]<ans[i+1]) {
                 sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y +1;
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2005
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int sz[N+N];
int lenx[N+N][N],leny[N+N][N],vis[N][N];
int n,k;
vector< string > ar(N);
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    lenx[0][0] = 0; leny[0][0] = 0;
    ans[0] = ar[0][0];
    sz[0] = 1;
    for(int i=0;i<n+n-1;i++){
        for(int k = 0;k<sz[i];k++){
            int x = lenx[i][k]; int y = leny[i][k];
            if(check(x+1,y)&&!vis[x+1][y]){
              if(ar[x+1][y]==ans[i+1]){
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  vis[x+1][y] = 1;
              }
              else if(ar[x+1][y]<ans[i+1]) {
                  sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x+1 ;
                  leny[i+1][sz[i+1]++] = y ;
                  ans[i+1] = ar[x+1][y];
                  vis[x+1][y] = 1;
              }
            }
            if(check(x,y+1)&&!vis[x][y+1]){
                vis[x][y+1] = 1;
              if(ar[x][y+1]==ans[i+1])  {
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y+1 ;
              }
              else if(ar[x][y+1]<ans[i+1]) {
                 sz[i+1] = 0;
                  lenx[i+1][sz[i+1]] = x ;
                  leny[i+1][sz[i+1]++] = y +1;
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2005
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
int vis[N][N];
vector< vector< pair< int ,int > > >  len(N+N);
int n,k;
vector< string > ar;
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    ar.resize(n);
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    len[0].pb({0,0});
    ans[0] = ar[0][0];
    for(int i=0;i<n+n-1;i++){
        for(auto j: len[i]){
            int x = j.x; int y = j.y;
            if(check(x+1,y)&&!vis[x+1][y]){
                vis[x+1][y] = 1;
              if(ar[x+1][y]==ans[i+1])  len[i+1].pb({x+1,y});
              else if(ar[x+1][y]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x+1,y});
                  ans[i+1] = ar[x+1][y];
              }
            }
            if(check(x,y+1)&&!vis[x][y+1]){
                vis[x][y+1] = 1;
              if(ar[x][y+1]==ans[i+1])  len[i+1].pb({x,y+1});
              else if(ar[x][y+1]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x,y+1});
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include<bits/stdc++.h>
#define N 2001
#define int int
#define pb push_back
#define x first
#define y second
using namespace std;
char ans[N+N];
vector< vector< pair< int ,int > > >  len(N+N);
int n,k;
vector< string > ar;
bool check(int x, int y){
    if(x>=0&&x<n&&y>=0&&y<n)return 1;
    return 0;
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin>>n>>k;
    ar.resize(n);
    for(int i=0;i<N+N;i++)
        ans[i] = 'z';
    for(int i=0;i<n;i++)
        cin>>ar[i];
    len[0].pb({0,0});
    ans[0] = ar[0][0];
    for(int i=0;i<n+n-1;i++){
        for(auto j: len[i]){
            int x = j.x; int y = j.y;
            if(check(x+1,y)){
              if(ar[x+1][y]==ans[i+1])  len[i+1].pb({x+1,y});
              else if(ar[x+1][y]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x+1,y});
                  ans[i+1] = ar[x+1][y];
              }
            }
            if(check(x,y+1)){
              if(ar[x][y+1]==ans[i+1])  len[i+1].pb({x,y+1});
              else if(ar[x][y+1]<ans[i+1]) {
                  len[i+1].clear();
                  len[i+1].pb({x,y+1});
                  ans[i+1] = ar[x][y+1];
              }
              continue;
            }
        }
        if(k&&ans[i]!='a'){
            ans[i]='a';
            k--;
        }
    }
    for(int i=0;i<n+n-1;i++)
        cout<<ans[i];
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ii = array<int, 2>;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, k;
    cin >> n >> k;

    vector<vector<ii>> dp(n + 1, vector<ii>(n + 1, {26, 1000000000}));
    vector<vector<int>> grid(n + 1, vector<int>(n + 1)), good(n + 1, vector<int>(n + 1));

    for(int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        for(int j = 1; j <= n; j++)
            grid[i][j] = (s[j - 1] - 'a');
    }
    string ans;
    dp[0][1] = dp[1][0] = {0, 0};
    good[0][1] = good[1][0] = 1;
    for(int s = 2; s <= 2*n; s++) {
        ii glo = {26, 1000000000};
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(good[r - 1][c]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r - 1][c][1]});
                if(dp[r - 1][c][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r - 1][c][1] + 1});
            }
            if(good[r][c - 1]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r][c - 1][1]});
                if(dp[r - 1][c][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r][c - 1][1] + 1});
            }
            glo = min(glo, dp[r][c]);
        }
        ans += ('a' + glo[0]);
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(dp[r][c][0] == glo[0])
                good[r][c] = 1;
        }
        cout << glo[0] << endl;
    }
    cout << ans << '\n';
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ii = array<int, 2>;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, k;
    cin >> n >> k;

    vector<vector<ii>> dp(n + 1, vector<ii>(n + 1, {26, 1000000000}));
    vector<vector<int>> grid(n + 1, vector<int>(n + 1)), good(n + 1, vector<int>(n + 1));

    for(int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        for(int j = 1; j <= n; j++)
            grid[i][j] = (s[j - 1] - 'a');
    }
    string ans;
    dp[0][1] = dp[1][0] = {0, 0};
    good[0][1] = good[1][0] = 1;
    for(int s = 2; s <= 2*n; s++) {
        ii glo = {26, 1000000000};
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(good[r - 1][c]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r - 1][c][1]});
                if(dp[r - 1][c][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r - 1][c][1] + 1});
            }
            if(good[r][c - 1]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r][c - 1][1]});
                if(dp[r][c - 1][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r][c - 1][1] + 1});
            }
            glo = min(glo, dp[r][c]);
        }
        ans += ('a' + glo[0]);
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(dp[r][c][0] == glo[0])
                good[r][c] = 1;
        }
        //cout << glo[0] << endl;
    }
    cout << ans << '\n';
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ii = array<int, 2>;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, k;
    cin >> n >> k;

    vector<vector<ii>> dp(n + 1, vector<ii>(n + 1, {26, 1000000000}));
    vector<vector<int>> grid(n + 1, vector<int>(n + 1)), good(n + 1, vector<int>(n + 1));

    for(int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        for(int j = 1; j <= n; j++)
            grid[i][j] = (s[j - 1] - 'a');
    }
    string ans;
    dp[0][1] = dp[1][0] = {0, 0};
    good[0][1] = good[1][0] = 1;
    for(int s = 2; s <= 2*n; s++) {
        ii glo = {26, 1000000000};
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(good[r - 1][c]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r - 1][c][1]});
                if(dp[r - 1][c][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r - 1][c][1] + 1});
            }
            if(good[r][c - 1]) {
                dp[r][c] = min(dp[r][c], {grid[r][c], dp[r][c - 1][1]});
                if(dp[r - 1][c][1] < k)
                    dp[r][c] = min(dp[r][c], ii{0, dp[r][c - 1][1] + 1});
            }
            glo = min(glo, dp[r][c]);
        }
        ans += ('a' + glo[0]);
        for(int r = 1; r <= min(n, s - 1); r++) {
            int c = s - r;
            if(c > n)
                continue;
            if(dp[r][c][0] == glo[0])
                good[r][c] = 1;
        }
        //cout << glo[0] << endl;
    }
    cout << ans << '\n';
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()) pq.push(make_tuple(2,v[1][1],1,1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    queue< tuple< int,char, int, int> > pq;
    int best = min(k+1,2*n);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if((i+j == best && dp[i][j] == k) || (i+j == 2*n && dp[i][j] <= k)){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.front();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] <= k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5
#define endl "\n"

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 2;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    assert(pq.size() > 0);
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || i+j == 2*n){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = k+1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if((i+j == best && dp[i][j] == k) || (i+j == 2*n && dp[i][j] <= k)){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = min(k+1,2*n);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if((i+j == best && dp[i][j] == k) || (i+j == 2*n && dp[i][j] <= k)){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5
#define endl "\n"

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < best-1; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5
#define endl "\n"

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k){
                pq.push(make_tuple(i+j,v[i][j],i,j));
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if(i+j == best && dp[i][j] == k){
                pq.push(make_tuple(i+j, v[i][j], i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if(a == 2*n){
            for(int i = 1; i < best; i++){
                cout << 'a';
            }
            for(int i = best+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] > (int)v[c+1][d]){
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] > (int)v[c][d+1]){
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}


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

#define int long long
#define INF 1e18+5

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    vector< vector<char> > v(n+1, vector<char>(n+1));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cin >> v[i][j];
        }
    }
    if(n == 1){
        if(k) cout << 'a' << endl;
        else cout << v[1][1] << endl;
        return 0;
    }
    vector< vector<int> > dp(n+1, vector<int>(n+1));
    for(int i = 0; i <= n; i++){
        dp[0][i] = dp[i][0] = INF;
    }
    dp[1][1] = (v[1][1] != 'a');
    priority_queue< tuple<int, char, int, int>, vector< tuple< int, char, int, int> >, greater< tuple<int, char, int, int> > > pq;
    int best = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] += min(dp[i-1][j], dp[i][j-1]) + (v[i][j] != 'a');
            if(dp[i][j] == k || ( dp[i][j] < k && i+j == 2*n)){
                best = max(best, i+j);
                //ADD TO THE QUEUE
            }
        }
    }
    for(int i = 1; i <=n; i++){
        for(int j = 1; j <= n; j++){
            if((i+j == best && dp[i][j] == k) || (i+j == 2*n && dp[i][j] <= k)){
                //cout << "PUSHED " << i << ' ' << j << endl;

                pq.push(make_tuple(i+j, 'a', i, j));
            }
        }
    }
    vector<int> depth(2*n+2, INF);
    depth[best] = (int)'a';
    //assert(pq.size() > 0);
    if(pq.empty()){
        pq.push(make_tuple(2,v[1][1],1,1));
        depth[2] = v[1][1];
    }
    vector< vector< bool > > visited(n+1, vector<bool>(n+1));
    while(!pq.empty()){
        auto p = pq.top();
        pq.pop();
        int a = get<0>(p);
        char b = get<1>(p);
        int c = get<2>(p);
        int d = get<3>(p);
        if((int)b != depth[a]) continue;
        if(a == 2*n){
            for(int i = 0; i < max(best-1,k); i++){
                cout << 'a';
            }
            for(int i = max(best,k)+1; i <= 2*n; i++){
                cout << (char)depth[i];
            }
            cout << endl;
            return 0;
        }
        else{
            if(c + 1 <= n && depth[a+1] >= (int)v[c+1][d] && !visited[c+1][d]){
                visited[c+1][d] = true;
                depth[a+1] = (int)v[c+1][d];
                pq.push(make_tuple(a+1,v[c+1][d],c+1,d));
            }
            if(d + 1 <= n && depth[a+1] >= (int)v[c][d+1] && !visited[c][d+1]){
                visited[c][d+1] = true;
                depth[a+1] = (int)v[c][d+1];
                pq.push(make_tuple(a+1,v[c][d+1],c,d+1));
            }
        }
    }
}