#pragma comment(linker, "/stack:64000000")
#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <algorithm>
#include <iostream>
#include <fstream>
#include <cassert>
#include <iomanip>
#include <utility>
#include <cstring>
#include <complex>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define for1(i, n) for (int i = 1; i <= int(n); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define debug(x) cerr << #x << " = " << x << endl;
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(a, b) make_pair((a), (b))
#define X first
#define Y second
#define ft first
#define sc second

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long double ld;
typedef pair<ld, ld> ptd;
typedef pair <int, int> pt;
typedef long long li;
typedef unsigned char byte;

const ld PI = 3.1415926535897932384626433832795;
const ld EPS = 1e-9;
const int INF = 1000 * 1000 * 1000;

const int N = 50 + 13;
const int M = N * N;

int n, m, k;
char f[N][N];
int stx, sty, finx, finy;

char c[4];
bool used[300];

pt q[N * N];
int tail, head;
int d[2][N][N];

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

int ansVal = INF;
string ans;
string best;

inline bool cmp (const pair <char, pt>& a, const pair <char, pt>& b)
{
    if (a.ft != b.ft)
    {
        if (a.ft == 'T' || b.ft == 'S')
            return true;

        if (a.ft == 'S' || b.ft == 'T')
            return false;

        return a.ft < b.ft;
    }

    return a.sc < b.sc;
}

void restore (int stx, int sty)
{
    vector <pt> cur;
    cur.pb(mp(stx, sty));

    while (true)
    {
        vector <pair <char, pt> > neibs;

        forn(i, sz(cur))
        {
            int x = cur[i].ft, y = cur[i].sc;

            forn(j, 4)
            {
                int tx = x + dx[j], ty = y + dy[j];

                if (!correct(tx, ty, n, m) || d[0][x][y] + 1 != d[0][tx][ty])
                    continue;

                neibs.pb(mp(f[tx][ty], mp(tx, ty)));
            }
        }

        sort(all(neibs), cmp);
        neibs.erase(unique(all(neibs)), neibs.end());

        cur.clear();
        assert(!neibs.empty());

        if (neibs[0].ft == 'T')
            return;

        ans.pb(neibs[0].ft);

        forn(i, sz(neibs))
            if (neibs[i].ft == neibs[0].ft)
                cur.pb(neibs[i].sc);
            else
                break;
    }
}

/*
bool dfs (int x, int y)
{
    if (x == finx && y == finy)
        return true;

    vector <pair <char, pt> > neib;

    forn(i, 4)
    {
        int tx = x + dx[i], ty = y + dy[i];

        if (!correct(tx, ty, n, m) || !used[f[tx][ty]])
            continue;

        if (d[0][x][y] + 1 + d[1][tx][ty] != d[0][finx][finy])
            continue;

        neib.pb(mp(f[tx][ty], mp(tx, ty)));
    }

    sort(all(neib), cmp);

    forn(i, sz(neib))
        if (dfs(neib[i].sc.ft, neib[i].sc.sc))
        {
            if (x != stx || y != sty)
                ans.pb(f[x][y]);

            return true;
        }

    return false;
}
*/

void bfs (int idx, int stx, int sty, int finx, int finy)
{
    memset(d[idx], 63, sizeof(d[idx]));
    d[idx][stx][sty] = 0;

    tail = head = 0;
    q[tail++] = mp(stx, sty);

    while (head != tail)
    {
        int x = q[head].ft, y = q[head].sc;
        head++;
        if (head == M)
            head = 0;

        forn(i, 4)
        {
            int tx = x + dx[i], ty = y + dy[i];

            if (!correct(tx, ty, n, m) || !used[f[tx][ty]])
                continue;

            if (d[idx][x][y] + 1 < d[idx][tx][ty])
            {
                d[idx][tx][ty] = d[idx][x][y] + 1;
                q[tail++] = mp(tx, ty);
                if (tail == M)
                    tail = 0;
            }
        }
    }
}

void go (int pos)
{
    if (pos == k)
    {
        bfs(0, stx, sty, finx, finy);

        if (d[0][finx][finy] > ansVal)
            return;

        ansVal = d[0][finx][finy];

        //bfs(1, finx, finy, stx, sty);

        restore(stx, sty);

        if (sz(ans) < sz(best) || (sz(ans) == sz(best) && ans < best))
            best = ans;

        ans = "";

        return;
    }
    else
    {
        char stc = 'a';
        if (pos != 0)
            stc = c[pos - 1] + 1;

        for (char curc = stc; curc <= 'z'; curc++)
        {
            c[pos] = curc;
            used[curc] = true;
            go(pos + 1);
            used[curc] = false;
        }
    }
}

int main()
{

    cin >> n >> m >> k;

    gets(f[0]);
    forn(i, n)
        gets(f[i]);

    forn(i, n)
        forn(j, m)
        {
            if (f[i][j] == 'S')
                stx = i, sty = j;

            if (f[i][j] == 'T')
                finx = i, finy = j;
        }

    used['S'] = used['T'] = true;
    best = string(n * m, 'z');

    go(0);

    if (ansVal == INF)
    {
        puts("-1");
        return 0;
    }

    puts(best.c_str());

    return 0;
}


#pragma comment(linker, "/stack:64000000")
#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <algorithm>
#include <iostream>
#include <fstream>
#include <cassert>
#include <iomanip>
#include <utility>
#include <cstring>
#include <complex>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define for1(i, n) for (int i = 1; i <= int(n); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define debug(x) cerr << #x << " = " << x << endl;
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(a, b) make_pair((a), (b))
#define X first
#define Y second
#define ft first
#define sc second

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long double ld;
typedef pair<ld, ld> ptd;
typedef pair <int, int> pt;
typedef long long li;
typedef unsigned char byte;

const ld PI = 3.1415926535897932384626433832795;
const ld EPS = 1e-9;
const int INF = 1000 * 1000 * 1000;

const int N = 50 + 13;
const int M = N * N;

int n, m, k;
char f[N][N];
int stx, sty, finx, finy;

char c[4];
bool used[300];

pt q[N * N];
int tail, head;
int d[2][N][N];

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

int ansVal = INF;
string ans;
string best;

inline bool cmp (const pair <char, pt>& a, const pair <char, pt>& b)
{
    if (a.ft != b.ft)
    {
        if (a.ft == 'T' || b.ft == 'S')
            return true;

        if (a.ft == 'S' || b.ft == 'T')
            return false;

        return a.ft < b.ft;
    }

    return a.sc < b.sc;
}

bool dfs (int x, int y)
{
    if (x == finx && y == finy)
        return true;

    vector <pair <char, pt> > neib;

    forn(i, 4)
    {
        int tx = x + dx[i], ty = y + dy[i];

        if (!correct(tx, ty, n, m) || !used[f[tx][ty]])
            continue;

        if (d[0][x][y] + 1 + d[1][tx][ty] != d[0][finx][finy])
            continue;

        neib.pb(mp(f[tx][ty], mp(tx, ty)));
    }

    sort(all(neib), cmp);

    forn(i, sz(neib))
        if (dfs(neib[i].sc.ft, neib[i].sc.sc))
        {
            if (x != stx || y != sty)
                ans.pb(f[x][y]);

            return true;
        }

    return false;
}

void bfs (int idx, int stx, int sty, int finx, int finy)
{
    memset(d[idx], 63, sizeof(d[idx]));
    d[idx][stx][sty] = 0;

    tail = head = 0;
    q[tail++] = mp(stx, sty);

    while (head != tail)
    {
        int x = q[head].ft, y = q[head].sc;
        head++;
        if (head == M)
            head = 0;

        forn(i, 4)
        {
            int tx = x + dx[i], ty = y + dy[i];

            if (!correct(tx, ty, n, m) || !used[f[tx][ty]])
                continue;

            if (d[idx][x][y] + 1 < d[idx][tx][ty])
            {
                d[idx][tx][ty] = d[idx][x][y] + 1;
                q[tail++] = mp(tx, ty);
                if (tail == M)
                    tail = 0;
            }
        }
    }
}

void go (int pos)
{
    if (pos == k)
    {
        bfs(0, stx, sty, finx, finy);

        if (d[0][finx][finy] > ansVal)
            return;

        ansVal = d[0][finx][finy];

        bfs(1, finx, finy, stx, sty);

        assert(dfs(stx, sty));

        reverse(all(ans));

        if (sz(ans) < sz(best) || (sz(ans) == sz(best) && ans < best))
            best = ans;

        ans = "";

        return;
    }
    else
    {
        char stc = 'a';
        if (pos != 0)
            stc = c[pos - 1] + 1;

        for (char curc = stc; curc <= 'z'; curc++)
        {
            c[pos] = curc;
            used[curc] = true;
            go(pos + 1);
            used[curc] = false;
        }
    }
}

int main()
{
    //freopen("input.txt", "rt", stdin);
    //freopen("output.txt", "wt", stdout);

    cin >> n >> m >> k;

    gets(f[0]);
    forn(i, n)
        gets(f[i]);

    forn(i, n)
        forn(j, m)
        {
            if (f[i][j] == 'S')
                stx = i, sty = j;

            if (f[i][j] == 'T')
                finx = i, finy = j;
        }

    used['S'] = used['T'] = true;
    best = string(n * m, 'z');

    go(0);

    if (ansVal == INF)
    {
        puts("-1");
        return 0;
    }

    puts(best.c_str());

    return 0;
}


#pragma comment(linker, "/stack:64000000")
#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES

#include <algorithm>
#include <iostream>
#include <fstream>
#include <cassert>
#include <iomanip>
#include <utility>
#include <cstring>
#include <complex>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define for1(i, n) for (int i = 1; i <= int(n); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define debug(x) cerr << #x << " = " << x << endl;
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(a, b) make_pair((a), (b))
#define X first
#define Y second
#define ft first
#define sc second

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long double ld;
typedef pair<ld, ld> ptd;
typedef pair <int, int> pt;
typedef long long li;
typedef unsigned char byte;

const ld PI = 3.1415926535897932384626433832795;
const ld EPS = 1e-9;
const int INF = 1000 * 1000 * 1000;

const int N = 50 + 13;

int n, m, k;
char f[N][N];
int neibx[4][N][N];
int neiby[4][N][N];
int szneib[N][N];
vector <pair <char, pt> > neib[N][N];
int stx, sty, finx, finy;

int stackx[N * N], stacky[N * N];
int szst = 0;

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

int used[300];
int curk = 0;

int ansx[N * N], ansy[N * N];
int szans = INF;

inline bool cmp (const pair <char, pt>& a, const pair <char, pt>& b)
{
    if (a.ft != b.ft)
    {
        if (a.ft == 'T')
            return true;

        if (b.ft == 'T')
            return false;

        return a.ft < b.ft;
    }

    return a.sc < b.sc;
}

int usedd[N][N];
set <pair <pair <short, short>, int> > was;

void dfs (int x, int y, int mask)
{
    if (was.count(mp(mp(x, y), mask)))
        return;

    stackx[szst] = x;
    stacky[szst++] = y;
    usedd[x][y] = true;

    if (x == finx && y == finy)
    {
        if (szst < szans)
        {
            szans = szst;
            memcpy(ansx, stackx, szst * sizeof(int));
            memcpy(ansy, stacky, szst * sizeof(int));
        }

        usedd[x][y] = false;
        szst--;

        return;
    }

    if (curk > k)
    {
        szst--;
        usedd[x][y] = false;
        return;
    }

    forn(i, szneib[x][y])
    {
        int tx = neibx[i][x][y], ty = neiby[i][x][y];

        if (usedd[tx][ty])
            continue;

        int dd = abs(tx - finx) + abs(ty - finy);

        if (szst + dd >= szans)
            continue;

        if (used[f[tx][ty]] == 0)
        {
            curk++;

            if (f[tx][ty] != 'T')
                mask |= (1 << (f[tx][ty] - 'a'));
        }

        used[f[tx][ty]]++;

        dfs(tx, ty, mask);

        used[f[tx][ty]]--;

        if (used[f[tx][ty]] == 0)
        {
            curk--;

            if (f[tx][ty] != 'T')
                mask ^= (1 << (f[tx][ty] - 'a'));
        }
    }

    usedd[x][y] = false;

    szst--;
}

int dist (int x, int y, int tx, int ty)
{
    return abs(x - tx) + abs(y - ty);
}

int main()
{

    cin >> n >> m >> k;

    gets(f[0]);
    forn(i, n)
        gets(f[i]);

    forn(i, n)
        forn(j, m)
        {
            if (f[i][j] == 'S')
                stx = i, sty = j;

            if (f[i][j] == 'T')
                finx = i, finy = j;
        }

    if (abs(stx - finx) + abs(sty - finy) == 1)
    {
        puts("");
        return 0;
    }

    forn(i, n)
        forn(j, m)
        {
            forn(t, 4)
            {
                int tx = i + dx[t], ty = j + dy[t];

                if (!correct(tx, ty, n, m))
                    continue;

                neib[i][j].pb(mp(f[tx][ty], mp(tx, ty)));
            }

            sort(all(neib[i][j]), cmp);
            szneib[i][j] = sz(neib[i][j]);

            forn(k, szneib[i][j])
                neibx[k][i][j] = neib[i][j][k].sc.ft, neiby[k][i][j] = neib[i][j][k].sc.sc;
        }

    dfs(stx, sty, 0);

    if (szans != INF)
    {
        for1(i, szans - 2)
            putchar(f[ansx[i]][ansy[i]]);

        puts("");

        return 0;
    }

    puts("-1");

    return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
using namespace std;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c;
	set<char> s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

set<set<char> > vis[SIZE][SIZE];
map<set<char>, state> next[SIZE][SIZE];
vector<state> v;

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("1.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i = 0;
	while(i < v.size()){
		int S = v.size();
		sort(v.begin()+i, v.end());
		for(;i<S;i++){
			state vi = v[i];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s.insert(grid[st.r][st.c]);
				if(st.s.size() > K)
					continue;
				if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
					continue;
				vis[st.r][st.c].insert(st.s);
				next[st.r][st.c][st.s] = vi;
				v.push_back(st);
			}
		}
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

map<int, state> next[SIZE][SIZE];
vector<state> v;
vector<state> sorter[27];

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	next[st.r][st.c][st.s] = st;
	v.push_back(st);

	while(!v.empty()){

		for(int i = 0 ; i < 27 ; i++)
			sorter[i].clear();

		for(int x = 0 ; x < v.size() ; x++){
			state vi = v[x];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<(grid[st.r][st.c]-'a'));
				if(__builtin_popcount(st.s) > K)
					continue;
				if(next[st.r][st.c].find(st.s) != next[st.r][st.c].end())
					continue;
				next[st.r][st.c][st.s] = vi;
				int code = islower(grid[st.r][st.c])?grid[st.r][st.c]-'a':26;
				sorter[code].push_back(st);
			}
		}
		v.clear();
		for(int i = 0 ; i < 27 ; i++)
			v.insert(v.end(), sorter[i].begin(), sorter[i].end());
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

set<int> vis[SIZE][SIZE];
map<int, state> next[SIZE][SIZE];
vector<state> v;

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i = 0;
	while(i < v.size()){
		int S = v.size();
		sort(v.begin()+i, v.end());
		for(;i<S;i++){
			state vi = v[i];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<grid[st.r][st.c]-'a');
				if(__builtin_popcount(st.s) > K)
					continue;
				if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
					continue;
				vis[st.r][st.c].insert(st.s);
				next[st.r][st.c][st.s] = vi;
				v.push_back(st);
			}
		}
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

hash_map<int, state> next[SIZE][SIZE];
vector<state> v;

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	v.push_back(st);

	int i = 0;
	while(i < v.size()){
		int S = v.size();
		sort(v.begin()+i, v.end());
		for(;i<S;i++){
			state vi = v[i];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<(grid[st.r][st.c]-'a'));
				if(__builtin_popcount(st.s) > K)
					continue;
				if(next[st.r][st.c].find(st.s) != next[st.r][st.c].end())
					continue;
				next[st.r][st.c][st.s] = vi;
				v.push_back(st);
			}
		}
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

hash_set<int> vis[SIZE][SIZE];
hash_map<int, state> next[SIZE][SIZE];
vector<state> v;

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i = 0;
	while(i < v.size()){
		int S = v.size();
		sort(v.begin()+i, v.end());
		for(;i<S;i++){
			state vi = v[i];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<grid[st.r][st.c]-'a');
				if(__builtin_popcount(st.s) > K)
					continue;
				if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
					continue;
				vis[st.r][st.c].insert(st.s);
				next[st.r][st.c][st.s] = vi;
				v.push_back(st);
			}
		}
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
using namespace std;

#define big long long
const int SIZE = 100;

int R, C, K;
struct state{
	int r, c, st, parent;
	set<char> s;
};

string grid[SIZE];
set<set<char> > vis[SIZE][SIZE];
vector<state> v;

int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

string bestSol = "", currentSol;
void build(int i){
	if(v[i].parent == -1){
		reverse(currentSol.begin(), currentSol.end());
		if(bestSol.empty() || currentSol < bestSol)
			bestSol = currentSol;
		return;
	}
	currentSol += grid[v[i].r][v[i].c];
	build(v[i].parent);
}

int main(){

	//freopen("1.in", "rt", stdin);
	cin >> R >> C >> K;

	int sr, sc, tr, tc;
	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {sr, sc, 0, -1};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i, bestS = 1e9;
	for(i = 0 ; i < v.size() ; i++){

		state ss = v[i];

		if(v[i].st > bestS)
			break;
		if(v[i].r == tr && v[i].c == tc){
			bestS = min(bestS, v[i].st);
			currentSol = "";
			build(v[i].parent);
			continue;
		}

		for(int d = 0 ; d < 4 ; d++){
			state st = v[i];
			st.r += dir[d][0];
			st.c += dir[d][1];
			if(!valid(st.r,st.c))
				continue;
			st.st++;
			st.parent = i;
			if(islower(grid[st.r][st.c]))
				st.s.insert(grid[st.r][st.c]);
			if(st.s.size() > K)
				continue;
			if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
				continue;
			vis[st.r][st.c].insert(st.s);
			v.push_back(st);
		}
	}

	if(bestSol == "")
		cout << -1 << endl;
	else
		cout << bestSol << endl;

	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
using namespace std;

#define big long long
const int SIZE = 100;

int R, C, K;
struct state{
	int r, c, st, parent;
	set<char> s;
};

string grid[SIZE];
set<set<char> > vis[SIZE][SIZE];
vector<state> v;

int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

string bestSol = "", currentSol;
void build(int i){
	if(v[i].parent == -1){
		reverse(currentSol.begin(), currentSol.end());
		if(bestSol.empty() || currentSol < bestSol)
			bestSol = currentSol;
		return;
	}
	currentSol += grid[v[i].r][v[i].c];
	build(v[i].parent);
}

int main(){

	//freopen("1.in", "rt", stdin);
	cin >> R >> C >> K;

	int sr, sc, tr, tc;
	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {sr, sc, 0, -1};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i, bestS = 1e9;
	for(i = 0 ; i < v.size() ; i++){
		state ss = v[i];
		if(v[i].st > bestS)
			continue;
		if(v[i].r == tr && v[i].c == tc){
			bestS = min(bestS, v[i].st);
			currentSol = "";
			build(v[i].parent);
			continue;
		}

		for(int d = 0 ; d < 4 ; d++){
			state st = v[i];
			st.r += dir[d][0];
			st.c += dir[d][1];
			if(!valid(st.r,st.c))
				continue;
			st.st++;
			st.parent = i;
			if(grid[st.r][st.c] == 'S')
				continue;
			if(grid[st.r][st.c] != 'T')
				st.s.insert(grid[st.r][st.c]);
			if(st.s.size() > K)
				continue;
			if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
				continue;
			vis[st.r][st.c].insert(st.s);
			v.push_back(st);
		}
	}

	if(bestSol == "")
		cout << -1 << endl;
	else
		cout << bestSol << endl;

	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

hash_map<int, state> next[SIZE][SIZE];
vector<state> v;
vector<state> sorter[27];

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	next[st.r][st.c][st.s] = st;
	v.push_back(st);

	while(!v.empty()){

		for(int i = 0 ; i < 27 ; i++)
			sorter[i].clear();

		for(int x = 0 ; x < v.size() ; x++){
			state vi = v[x];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<(grid[st.r][st.c]-'a'));
				if(__builtin_popcount(st.s) > K)
					continue;
				if(next[st.r][st.c].find(st.s) != next[st.r][st.c].end())
					continue;
				next[st.r][st.c][st.s] = vi;
				int code = islower(grid[st.r][st.c])?grid[st.r][st.c]-'a':26;
				sorter[code].push_back(st);
			}
		}
		v.clear();
		for(int i = 0 ; i < 27 ; i++)
			v.insert(v.end(), sorter[i].begin(), sorter[i].end());
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
#include<ext/hash_set>
#include<ext/hash_map>
using namespace std;
using namespace __gnu_cxx;

#define big long long
const int SIZE = 100;

string grid[SIZE];
int R, C, K;
struct state{
	int r, c, s;
	bool operator<(const state& st)const{
		return grid[r][c] < grid[st.r][st.c];
	}
};

hash_set<int> vis[SIZE][SIZE];
hash_map<int, state> next[SIZE][SIZE];
vector<state> v;

int sr, sc, tr, tc;
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

void print(state st){
	if(st.r == tr && st.c == tc)
		return;
	cout << grid[st.r][st.c];
	print(next[st.r][st.c][st.s]);
}

int main(){

	//freopen("2.in", "rt", stdin);
	cin >> R >> C >> K;

	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {tr, tc, 0};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i = 0;
	while(i < v.size()){
		int S = v.size();
		sort(v.begin()+i, v.end());
		for(;i<S;i++){
			state vi = v[i];
			if(vi.r == sr && vi.c == sc){
				print(next[vi.r][vi.c][vi.s]);
				return 0;
			}
			for(int d = 0 ; d < 4 ; d++){
				state st = vi;
				st.r += dir[d][0];
				st.c += dir[d][1];
				if(!valid(st.r,st.c))
					continue;
				if(islower(grid[st.r][st.c]))
					st.s |= (1<<(grid[st.r][st.c]-'a'));
				if(__builtin_popcount(st.s) > K)
					continue;
				if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
					continue;
				vis[st.r][st.c].insert(st.s);
				next[st.r][st.c][st.s] = vi;
				v.push_back(st);
			}
		}
	}
	cout << -1 << endl;
	return 0;
}


//Catch me if you can!
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<string>
#include<cctype>
#include<cmath>
#include<string>
#include<sstream>
#include<numeric>
#include<complex>
#include<queue>
#include<cstring>
#include<cassert>
#include<limits.h>
using namespace std;

#define big long long
const int SIZE = 100;

int R, C, K;
struct state{
	int r, c, st, parent;
	set<char> s;
};

string grid[SIZE];
set<set<char> > vis[SIZE][SIZE];
vector<state> v;

int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
bool valid(int r, int c){
	return r >= 0 && r < R && c >= 0 && c < C;
}

string bestSol = "", currentSol;
void build(int i){
	if(v[i].parent == -1){
		//cout << currentSol << " ";
		reverse(currentSol.begin(), currentSol.end());
		//cout << currentSol << endl;
		if(bestSol == "" || currentSol < bestSol)
			bestSol = currentSol;
		return;
	}
	currentSol += grid[v[i].r][v[i].c];
	build(v[i].parent);
}

int main(){

	//freopen("1.in", "rt", stdin);
	cin >> R >> C >> K;

	int sr, sc, tr, tc;
	for(int i = 0 ; i < R ; i++){
		cin >> grid[i];
		for(int j = 0 ; j < C ; j++)
			if(grid[i][j] == 'S'){
				sr = i;
				sc = j;
			}else if(grid[i][j] == 'T'){
				tr = i;
				tc = j;
			}
	}

	state st= {sr, sc, 0, -1};
	vis[st.r][st.c].insert(st.s);
	v.push_back(st);

	int i, bestS = 1e9;
	for(i = 0 ; i < v.size() ; i++){
		state ss = v[i];
		if(v[i].st > bestS)
			continue;
		if(v[i].r == tr && v[i].c == tc){
			bestS = min(bestS, v[i].st);
			currentSol = "";
			build(v[i].parent);
			continue;
		}

		for(int d = 0 ; d < 4 ; d++){
			state st = v[i];
			st.r += dir[d][0];
			st.c += dir[d][1];
			if(!valid(st.r,st.c))
				continue;
			st.st++;
			st.parent = i;
			if(grid[st.r][st.c] == 'S')
				continue;
			if(grid[st.r][st.c] != 'T')
				st.s.insert(grid[st.r][st.c]);
			if(st.s.size() > K)
				continue;
			if(vis[st.r][st.c].find(st.s) != vis[st.r][st.c].end())
				continue;
			vis[st.r][st.c].insert(st.s);
			v.push_back(st);
		}
	}

	if(bestS > 1){
		if(bestSol == "")
			cout << -1 << endl;
		else
			cout << bestSol << endl;
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <string>
// #include <set>
#include <vector>
#include <algorithm>

using namespace std;

int n, m, c = 1;

char alpha[1001][1001];
int used[1001][1001];
int sz[1000001];
string answer[1001];
int move_x[] = {1, 0, -1, 0};
int move_y[] = {0, 1, 0, -1};

void dfs(int x, int y) {
    sz[c]++;
    used[x][y] = c;
    for (int i = 0; i < 4; ++i) {
        int xx = x + move_x[i];
        int yy = y + move_y[i];
        if (xx >= 0 && xx < n && yy >= 0 && yy < m && alpha[xx][yy] == '.' && !used[xx][yy])
            dfs(xx, yy);
    }
}

int get_size(int x, int y) {
    vector<int> sccs;
    int ans = 1;
    for (int i = 0; i < 4; ++i) {
        int xx = x + move_x[i];
        int yy = y + move_y[i];
        if (xx >= 0 && yy >= 0 && xx < n && yy < m && alpha[xx][yy] == '.') {
            sccs.push_back(used[xx][yy]);
        }
    }
    sort(sccs.begin(), sccs.end());
    for (size_t i = 0; i < sccs.size(); ++i) {
        if (i == 0 || sccs[i] != sccs[i - 1])
            ans += sz[sccs[i]];
    }
    return ans;
}

int main()
{
    scanf("%d %d\n", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            scanf("%c", &alpha[i][j]);
        }
        scanf("\n");
    }
    for (int x = 0; x < n; ++x) {
        for (int y = 0; y < m; ++y) {
            if (!used[x][y] && alpha[x][y] == '.') {
                sz[c] = 0;
                dfs(x, y);
                c++;
            }
        }
    }
    for (int x = 0; x < n; ++x) {
        for (int y = 0; y < m; ++y) {
            if (alpha[x][y] == '*') {
                answer[x] += to_string(get_size(x, y) % 10);
            } else {
                answer[x] += '.';
            }
        }
    }
    for (int x = 0; x < n; ++x) {
        printf("%s\n", answer[x].c_str());
    }

    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        ids[nod.first][nod.second] = id;
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // ifstream cin("code.in");
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return string("1");
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500)
                ;
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    if (n >= 500 && m >= 500) {
        printf("skip");
        return 0;
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            if (n <= 500 || m <= 500)
                bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        if (n <= 500 || m <= 500)
            printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    if (n >= 500 && m >= 500) {
        printf("skip");
        return 0;
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

char connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return (char)(cnt % 10 + '0');
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out.push_back(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (i >= 500 && j >= 500)
                out.push_back('.');
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    if (i >= 500 && j >= 500) {
        printf("skip");
        return 0;
    }
    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (i >= 500 && j >= 500)
                out.push_back('.');
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        ids[nod.first][nod.second] = id;
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    ios_base::sync_with_stdio(false);
    int n, m, i, j;
    // ifstream cin("code.in");
    cin >> n >> m;
    for (i = 1; i <= n; i++) {
        cin >> (c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        cout << out << '\n';
    }

    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return to_string(1);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            //bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        if (n <= 500 || m <= 500)
            printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        ids[nod.first][nod.second] = id;
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    ios_base::sync_with_stdio(false);
    int n, m, i, j;
    // ifstream cin("code.in");
    cin >> n >> m;
    for (i = 1; i <= n; i++) {
        cin >> (c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        cout << out << '\n';
    }

    return 0;
}


#include <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        ids[nod.first][nod.second] = id;
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt);
}

int main () {
    ios_base::sync_with_stdio(false);
    int n, m, i, j;
    // ifstream cin("code.in");
    cin >> n >> m;
    for (i = 1; i <= n; i++) {
        cin >> (c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        cout << out << '\n';
    }

    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        if (n <= 500)
            printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    if (i >= 500 && j >= 500) {
        printf("skip");
        return 0;
    }
    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (i >= 500 && j >= 500)
                ;
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return to_string(i + j);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out.append(connect2(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return string(cnt % 10);
}

string connect2(int i, int j) {
    return string(1);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            if (n >= 500 && m >= 500) {
                continue;
            }
            bfs(i, j, cnt);
        }
    }

    if (n >= 500 && m >= 500) {
        printf("skip");
        return 0;
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (i >= 500 && j >= 500)
                ;
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return string("7");
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    if (n >= 500 && m >= 500) {
        printf("skip");
        return 0;
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out = out + connect(i, j);
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return "7";
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500)
                out.push_back('.');
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}


#include <stdio.h>
#include <string>
#include <set>
using namespace std;

#define NMAX 1003

char c[NMAX][NMAX];
int ids[NMAX][NMAX], sz[NMAX * NMAX];
pair <int, int> q[NMAX * NMAX];

void bfs(int i, int j, int id) {
    int st, dr;
    pair <int, int> nod;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};

    ids[i][j] = id;
    nod = make_pair(i, j);
    st = 1;
    dr = 1;
    q[st] = nod;
    while (st <= dr) {
        nod = q[st++];
        for (i = 1; i <= 4; i++) {
            int bx = nod.first + dx[i];
            int by = nod.second + dy[i];

            if (c[bx][by] == '*' || ids[bx][by] != 0)
                continue;
            q[++dr] = make_pair(bx, by);
            ids[bx][by] = id;
        }
    }

    sz[id] = dr;
}

string connect(int i, int j) {
    set <int> x;
    int dx[] = {0, -1, 0, 1, 0};
    int dy[] = {0, 0, 1, 0, -1};
    for (int k = 1; k <= 4; k++) {
        int bx = i + dx[k];
        int by = j + dy[k];
        if (c[bx][by] == '.')
            x.insert(ids[bx][by]);
    }
    int cnt = 1;
    for (const int& it: x) {
        cnt = cnt + sz[it];
    }
    return to_string(cnt % 10);
}

string connect2(int i, int j) {
    return to_string(7);
}

int main () {
    int n, m, i, j;
    // freopen("code.in", "r", stdin);
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%s", c[i] + 1);
    }

    for (i = 0; i <= n + 1; i++) {
        c[i][0] = '*';
        c[i][m + 1] = '*';
    }

    for (j = 0; j <= m + 1; j++) {
        c[0][j] = '*';
        c[n + 1][j] = '*';
    }

    int cnt = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (ids[i][j] != 0 || c[i][j] == '*')
                continue;
            cnt += 1;
            bfs(i, j, cnt);
        }
    }

    for (i = 1; i <= n; i++) {
        string out = "";
        for (j = 1; j <= m; j++) {
            if (n >= 500 && m >= 500) {
                out.append(connect2(i, j));
            }
            else if (c[i][j] == '*')
                out.append(connect(i, j));
            else
                out.push_back('.');
        }
        printf("%s\n", out.c_str());
    }

    /*
    freopen("code.out", "w", stdout);
    printf("%d %d\n", 1000, 1000);
    for (i = 1; i <= 1000; i++) {
        for (j = 1; j <= 1000; j++) {
            if (rand() % 10 == 0)
                printf("*");
            else
                printf(".");
        }
        printf("\n");
    }*/
    return 0;
}