#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::less;
using std::map;
using std::min;
using std::ostream;
using std::set;
using std::sort;
using std::string;
using std::vector;

//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------

inline bool compare(const string& a, const string& b) {
    //	if(a[0] >= '0' && a[0] <= '9' && b[0] >= '0' && b[0] <= '9')
    //	{
    //		return atof(a.c_str()) < atof(b.c_str());
    //	}
    return a < b;
}

struct compare_alnum {
    bool operator()(const string& a, const string& b) { return compare(a, b); }
};

map<string, int> priorities;

class Column {
    int diff_;
    int prio_;
    string title_;
    vector<string>* value_;

public:
    Column() {}

    Column(const string& title, vector<string>* value) :
        title_(title),
        value_(value),
        prio_(priorities.find(title) != priorities.end() ? priorities[title] : 0),
        diff_(-1) {
#ifdef DEBUG
        cerr << title_ << " -> " << prio_ << endl;
#endif
    }


    int diff() const { return diff_; };
    int prio() const { return prio_; };

    friend bool operator<(const Column& a, const Column& b) {
        return a.prio() != b.prio() ? a.prio() > b.prio() : a.diff() < b.diff();
    }

    void computeDifferences(const vector<int>&);

    string& value(int i) { return (*value_)[i]; }
    const string& value(int i) const { return (*value_)[i]; }
    const string& title() const { return title_; }
};

void Column::computeDifferences(const vector<int>& idx) {
    set<string, less<string> > diff;
    for (size_t i = 0; i < idx.size(); i++)
        diff.insert(value(idx[i]));
    diff_ = diff.size();
}

class Table {
    vector<Column> cols_;
    vector<int> colidx_;
    vector<int> rowidx_;
    int depth_;
    ostream& out_;
    string prefix_;

public:
    Table(ostream& out, const string& prefix) :
        depth_(0), out_(out), prefix_(prefix){};

    Table(const Table&, int a, int b);

    void column(const string& s, vector<string>* col);
    void print();
    void sortCols();
    void sortRows();
    bool popSingles();
    void split();
    void process();
    vector<string> oneless(int, int);

    bool factorise(int);
    bool factorise();

    string& elem(int c, int r) { return cols_[colidx_[c]].value(rowidx_[r]); }

    int ncols() const { return colidx_.size(); }
    int nrows() const { return rowidx_.size(); }


    const Column& col(int i) const { return cols_[colidx_[i]]; }
    Column& col(int i) { return cols_[colidx_[i]]; }
    const string& title(int i) const { return cols_[colidx_[i]].title(); }
};

Table::Table(const Table& other, int a, int b) :
    depth_(other.depth_ + 1),
    cols_(other.cols_),
    colidx_(other.colidx_),
    rowidx_(other.rowidx_),
    out_(other.out_) {
    rowidx_.erase(rowidx_.begin() + b, rowidx_.end());
    rowidx_.erase(rowidx_.begin(), rowidx_.begin() + a);
}

void Table::column(const string& s, vector<string>* col) {
    cols_.push_back(Column(s, col));
    colidx_.push_back(colidx_.size());

    if (col->size() > nrows()) {
        rowidx_.resize(col->size());
        for (int i = 0; i < nrows(); i++)
            rowidx_[i] = i;
    }
}

#ifdef DEBUG

void Table::print() {
    for (int k = 0; k < depth_; k++)
        cerr << ' ';
    for (int i = 0; i < ncols(); i++)
        cerr << title(i) << "\t";
    cerr << endl;

    for (int i = 0; i < min(nrows(), 10); i++) {
        for (int k = 0; k < depth_; k++)
            cerr << ' ';
        for (int j = 0; j < ncols(); j++) {
            string& s = elem(j, i);
            cerr << s << "\t";
        }
        cerr << endl;
    }

    cerr << "rows = " << nrows() << " cols = " << ncols() << endl;
    cerr << endl;
}

#endif

vector<string> Table::oneless(int r, int n) {
    vector<string> v;
    v.reserve(ncols() - 1);
    for (int i = 0; i < ncols(); i++)
        if (i != n)
            v.push_back(elem(i, r));
    return v;
}

bool Table::factorise() {
    bool more = false;
    popSingles();
    sortRows();
    for (int i = 0; i < ncols(); i++)
        if (factorise(ncols() - i - 1))
            /* more =  true; */
            return true;
    return more;
}

string join(const set<string, compare_alnum>& v) {
    string s;
    for (set<string, compare_alnum>::const_iterator j = v.begin(); j != v.end(); ++j) {
        if (s.length())
            s += '/';
        s += *j;
    }
    return s;
}

bool Table::factorise(int n) {
    // if(ncols() < 2) return false;

#ifdef DEBUG
    cerr << "Factor " << title(n) << "  -> " << nrows() << endl;
    print();
#endif

    bool more = false;

    map<vector<string>, set<string, compare_alnum>, less<vector<string> > > remap;

    vector<string> prev;
    set<string, compare_alnum> acc;
    vector<int> idx;
    idx.resize(nrows());

    vector<int> gone;

    for (int i = 0; i < nrows(); i++) {
        vector<string> v              = oneless(i, n);
        set<string, compare_alnum>& s = remap[v];
        if (s.size() != 0)
            gone.push_back(i);
        s.insert(elem(n, i));
    }

    for (int i = gone.size() - 1; i >= 0; i--) {
        rowidx_.erase(rowidx_.begin() + gone[i], rowidx_.begin() + gone[i] + 1);
    }

    for (int i = 0; i < nrows(); i++) {
        vector<string> v              = oneless(i, n);
        set<string, compare_alnum>& s = remap[v];
        elem(n, i)                    = join(s);
    }

#ifdef DEBUG
    cerr << "Factor " << title(n) << " <- " << nrows() << endl;
    print();
#endif

    return more;
}

//---------------------------------------------------------
struct compare_cols {
    const vector<Column>& cols_;
    compare_cols(const vector<Column>& cols) :
        cols_(cols) {}

    bool operator()(int a, int b)
    // { return cols_[a].diff() < cols_[b].diff(); }
    { return cols_[a] < cols_[b]; }
};

void Table::sortCols() {
    for (int i = 0; i < ncols(); i++)
        col(i).computeDifferences(rowidx_);
    sort(colidx_.begin(), colidx_.end(), compare_cols(cols_));
#ifdef DEBUG
    for (int i = 0; i < ncols(); i++)
        cerr << "col " << i << " = " << title(i) << endl;
#endif
}

//---------------------------------------------------------
struct compare_rows {
    const vector<Column>& cols_;
    const vector<int>& colidx_;
    compare_rows(const vector<Column>& cols, const vector<int>& colidx) :
        cols_(cols), colidx_(colidx) {}

    bool operator()(int a, int b) {
        for (int j = 0; j < colidx_.size(); j++) {
            const string& sa = cols_[colidx_[j]].value(a);
            const string& sb = cols_[colidx_[j]].value(b);
            if (sa != sb)
                return compare(sa, sb);
        }
        return false;
    }
};

void Table::sortRows() {
    sort(rowidx_.begin(), rowidx_.end(), compare_rows(cols_, colidx_));
}
//---------------------------------------------------------

bool Table::popSingles() {
    sortCols();
    bool ok = false;
    while (colidx_.size() > 0 && cols_[colidx_[0]].diff() == 1) {
        if (prefix_.length() == 0) {
            for (int k = 0; k < depth_; k++)
                prefix_ += " ";
        }
        else {
            prefix_ += ",";
        }
        prefix_ += col(0).title();
        prefix_ += "=";
        prefix_ += elem(0, 0);
        colidx_.erase(colidx_.begin(), colidx_.begin() + 1);
        ok = true;
    }
    return ok;
}

void Table::split() {
    if (nrows() < 2)
        return;

    sortCols();
    sortRows();

    string prev = elem(0, 0);
    int j       = 0;

    for (int i = 1; i < nrows(); i++) {
        string& e = elem(0, i);
        if (prev != e) {
            Table table(*this, j, i);
            table.process();
            j    = i;
            prev = e;
        }
    }

    if (j > 0) {
        Table table(*this, j, nrows());
        table.process();
        rowidx_.clear();
    }
}

//---------------------------------------------------------
void Table::process() {
    while (factorise())
        ;
    popSingles();
    out_ << prefix_ << endl;
    split();
}

//---------------------------------------------------------

int main(int argc, char** argv) {

    Table table(cout, "");

    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            priorities[argv[i] + 1] = -(argc - i);
        }
        else {
            priorities[argv[i]] = argc - i;
        }
    }

    int size1;
    int size2;
    cin >> size1;
    cin >> size2;

    vector<string> col;
    col.resize(size2);
    string title;
    while (size1-- > 0) {
        cin >> title;
        for (int i = 0; i < size2; i++)
            cin >> col[i];
        vector<string>* v = new vector<string>(col);
        table.column(title, v);
    }


    table.process();

    exit(0);
    return 0;
}
