#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
ifstream fin("bounce.in");
int r,c,n;
char grid[7][8]; long long goalUsed;
int toIndex(int j, int k) {
return j*(c+1) + k;
}
bool isvalid(int j, int k) {
return (j >= 0) && (j < r) && (k >= 0) && (k < c + j%2);
}
vector<pair<int,int> > hex_neighbors(int j, int k) {
vector<pair<int, int> > answers;
int steps[6][2] = { {j-1,k}, {j-1,k+1-(j%2)*2}, {j,k-1}, {j,k+1}, {j+1,k}, {j+1,k+1-(j%2)*2}}; for (int z=0; z<6; z++) {
int a(steps[z][0]), b(steps[z][1]);
if (isvalid(a,b))
answers.push_back(make_pair(a,b));
}
return answers;
}
struct Path {
string pattern; int j,k; int length; long long used;
Path() : pattern(""), length(0), used(0) {}
Path(int j, int k, const Path& prev=Path()) : j(j), k(k) {
length = 1 + prev.length;
used = prev.used | (1LL<<toIndex(j,k));
pattern = prev.pattern;
if (pattern.size() < n)
pattern += grid[j][k];
}
bool operator<(const Path& other) const {
if (used < other.used)
return true;
if (used > other.used)
return false;
if (j < other.j || (j == other.j && k < other.k));
}
vector<Path> neighbors() const {
vector<Path> answers;
vector<pair<int,int> > candidates = hex_neighbors(j,k);
for (int i=0; i < candidates.size(); i++) {
int a=candidates[i].first;
int b=candidates[i].second;
int bit = toIndex(a,b);
if ((used & (1LL<<bit)) == 0) {
if (length < n || (grid[a][b] == pattern[length%n])) {
int trk = k+1-(j%2); if (j < r-1 || ((a==r-1 && b==k+1) || (a==r-2 && (b==trk || !isvalid(r-2,trk) || (used & (1LL<<toIndex(r-2,trk)) == 0))))) {
answers.push_back(Path(a,b,*this));
}
}
}
}
return answers;
}
};
map<Path, string> memory;
string complete(const Path& current) {
if (current.length == n)
memory.clear();
if (current.length > n) {
map<Path, string>::const_iterator ans = memory.find(current);
if (ans != memory.end())
return ans->second;
}
string best;
if (current.pattern.size() == n &&
current.length % current.pattern.size() == 0 &&
current.j == 0 &&
current.used >= goalUsed) {
while (best.size() < current.length)
best += current.pattern;
} else {
vector<Path> neigh = current.neighbors();
for (int i=0; i < neigh.size(); i++) {
string temp = complete(neigh[i]);
if (temp != "" && (best =="" || temp.size() < best.size()))
best = temp;
}
}
if (current.length > n) memory[current] = best;
return best;
}
int main() {
while (true) {
fin >> r;
if (r == 0) break;
fin >> c >> n;
for (int j=0; j < r; j++)
for (int k=0; k < c + j%2; k++)
fin >> grid[j][k];
string shortest;
goalUsed = (1LL << toIndex(r-1,0));
for (int k=0; k < c-1; k++) {
string temp = complete(Path(0,k));
if (temp != "" && (shortest == "" || temp.size() < shortest.size()))
shortest = temp;
}
if (shortest == "")
cout << "no solution" << endl;
else
cout << shortest << endl;
}
}