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

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

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

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(int 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;
}
