#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
#include <cassert>

typedef std::vector< std::vector<int> > Column;
typedef std::vector< Column > Block;
typedef std::vector<char> Used;

bool checkUp(size_t step, size_t pos,
        size_t curDigit, size_t digitsToCheck,
        const Column& up)
{
    size_t subStep = step / 10;
    for(size_t iter = 0; iter < digitsToCheck && pos > 0; ++iter) {
        size_t requiredNumbers = std::min(pos, subStep);
        if (requiredNumbers > up[curDigit][pos - 1]) {
            return false; 
        }
        pos -= requiredNumbers;
        curDigit = curDigit == 0 ? 9 : curDigit - 1;
    }
    return true;
}

bool checkDown(int step, int pos,
        int curDigit, int digitsToCheck,
        const Column& up)
{
    int size = up[0].size();
    int subStep = step / 10;
    for(size_t iter = 0; iter < digitsToCheck && pos < size; ++iter) {
        size_t requiredNumbers = std::min(subStep, size - pos);
        size_t lastPos = pos + requiredNumbers - 1;
        if (requiredNumbers > up[curDigit][lastPos]) {
            return false;
        }
        pos += requiredNumbers;
        curDigit = curDigit == 9 ? 0 : curDigit + 1;
    }
    return true;
}

bool canStartDigit(int step, int pos, int digit, const Column& up, const Used& isZero)
{
    int zeroUpPos = pos - (step / 10) * digit;
    int zeroDownPos = pos + (step / 10) * (10 - digit);

    if (zeroUpPos >= 0) {
        return isZero[zeroUpPos];
    }
    if (zeroDownPos < (int)isZero.size()) {
        return isZero[zeroDownPos];
    }
    
    bool bup = checkUp(step, pos, digit == 0 ? 9 : digit - 1, digit, up);
    bool bdown = checkDown(step, pos, digit, 10 - digit, up);
    return bup && bdown;
}

void updateZeroes(size_t step, Used& isZero, const Column& up)
{
    for(size_t i = 0; i < isZero.size(); ++i) {
        bool reallyZero = isZero[i];
        reallyZero = reallyZero && (i < step || isZero[i - step]);
        if (reallyZero) {
            reallyZero = checkUp(step, i, 9, 10, up);
        }
        //std::cerr << step << " !@# " << int(reallyZero) << " " << i << std::endl;
        isZero[i] = reallyZero;
    }

    for(int i = isZero.size() - 1; i >= 0; --i) {
        bool reallyZero = isZero[i];
        reallyZero = reallyZero && (i + step >= isZero.size() || isZero[i + step]);
        if (reallyZero) {
            reallyZero = checkDown(step, i, 0, 10, up);
        }
        //std::cerr << step << " !@# " << int(reallyZero) << " " << i << std::endl;
        isZero[i] = reallyZero;
    }
}

std::string inc(const std::string& a)
{
    std::string res = a;
    int ic = 1;
    for(int i = res.size() - 1; i >= 0 && ic; --i) {
        if (res[i] == '9') {
            res[i] = '0';
            ic = 1;
        } else {
            res[i] += 1;
            ic = 0;
        }
    }
    return res;
}

std::string dec(const std::string& a)
{
    std::string res = a;
    int dc = 1;
    for(int i = res.size() - 1; i >= 0 && dc; --i) {
        if (res[i] == '0') {
            res[i] = '9';
            dc = 1;
        } else {
            res[i] -= 1;
            dc = 0;
        }
    }
    return res;
}

char anyDigit(const std::string& s)
{
    char res = '*';
    for(size_t i = 0; i < s.size(); ++i) {
        char x = s[i];
        if (x != '*' && res == '*') res = x;
        if (x != '*' && res != x) return 0;
    }
    if (res == '*') return '1';
    return res;
}

void fillAns(std::vector<std::string>& calendar,
        int column, int pos, int digit) {
    calendar[pos][column] = '0' + digit;
    for(int i = column + 1; i < calendar[pos].size(); ++i) calendar[pos][i] = '0';

    for(int i = pos - 1; i >= 0; --i) calendar[i] = dec(calendar[i + 1]);
    for(int i = pos + 1; i < calendar.size(); ++i) calendar[i] = inc(calendar[i - 1]);
}

bool corresponds(int c, char pat)
{
    return pat == '*' || c + '0' == pat;
}

int pow10(int b)
{
    if (b > 8) return 1e+8; else return pow(10.0, b);
}

inline int pow10(size_t b)
{
	return pow10(int(b));
}

int main () {
	freopen("calendar.in", "r", stdin);
	freopen("calendar.out", "w", stdout);
    size_t n, m;
    std::cin >> n >> m;
    std::vector<std::string> calendar(n);
    for(int i = 0; i < n; ++i) {
        std::cin >> calendar[i];
    }
    Block up;
    size_t numColumns = calendar[0].size();

    up = Block(numColumns, Column(10, std::vector<int>(n, 0)));
    for(int column = numColumns - 1; column >= 0; --column) {
        Column& upColumn = up[column];
        std::string digitsColumn(n, '0');
        for(size_t t = 0; t < n; ++t) digitsColumn[t] = calendar[t][column];

        for(size_t digit = 0; digit < 10; ++digit) {
            std::vector<int>& curUp = upColumn[digit];

            curUp[0] = corresponds(digit, digitsColumn[0]);
            for(size_t t = 1; t < n; ++t) {
                curUp[t] = corresponds(digit, digitsColumn[t])
                    ? curUp[t - 1] + 1
                    : 0;
            }
        }
    }

    std::vector<Used> canZeroes(numColumns, Used(n, 1));
    Used& lastCanZeroes = canZeroes.back();
    for(size_t t = 0; t < n; ++t) {
        char symb = calendar[t][numColumns - 1];
        lastCanZeroes[t] = corresponds(0, symb);
    }
    size_t step = 1;
    updateZeroes(pow10(step), lastCanZeroes, up.back());

    for(int column = numColumns - 2; column >= 0; --column) {
        Used& curCanZeroes = canZeroes[column];
        Column& curUp = up[column];
        curCanZeroes = canZeroes[column + 1];

        for(size_t t = 0; t < n; ++t) {
            char symb = calendar[t][column];
            curCanZeroes[t] = curCanZeroes[t] && corresponds(0, '*');
        }
        step++;
        updateZeroes(pow10(step), curCanZeroes, up[column]);
    }

    bool ok = false;
    for(size_t column = 0; column < numColumns; ++column) {
        Column& curUp = up[column];
        Used& curIsZero = canZeroes[column];
        for(size_t digit = 0; digit < 10; ++digit) {
            for(size_t pos = 0; pos < n; ++pos) {
                if ((column + 1 >= numColumns || canZeroes[column + 1][pos]) &&
                    canStartDigit(pow10(step), pos, digit, curUp, curIsZero)) {

                    fillAns(calendar, column, pos, digit);
                    std::cerr << "Column: " << column << " Pos: " << pos << " Digit: " << digit << std::endl;
                    ok = true;
                    break;
                }
            }
            if (ok) break;
        }
        if (ok) break;
        std::string digitsColumn(n, '0');
        for(size_t t = 0; t < n; ++t) digitsColumn[t] = calendar[t][column];
        if (!ok) {
            char dig = anyDigit(digitsColumn);
            if (dig == 0 || column + 1 == numColumns) {
                assert(false);
                return 0;
            }
            for(size_t t = 0; t < n; ++t) calendar[t][column] = dig;
        }
        step--;
    }
	std::cout << calendar[0] << std::endl;
//    for(size_t t = 0; t < n; ++t) std::cout << calendar[t] << std::endl;
    return 0;
}

