#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <fstream>
using namespace std;
inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v;}
template<class T> inline string toStr(T x) { ostringstream sout; sout << x; return sout.str();}
typedef vector<int> vi;
typedef vector<vi>  vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define REP(i,n) FOR(i,0,(n)-1)
const double EPS = 1e-12;
const double PI = acos(-1.0);
const int INF = INT_MAX/10;

int h, w, n;

bool isEmptyField(vs field) {
	REP(i, h) {
		REP(j, w) {
			if(field[i][j] != '.') {
				return false;
			}
		}
	}
	return true;
}

vector<pii> getEraseHorizontalPoints(vs field) {
	vector<pii> res;
	vvi table(h, vi(w, 1));
	REP(i, h) {
		FOR(j, 1, w-1) {
			if(field[i][j] != '.') {
				if(field[i][j] == field[i][j-1]) {
					table[i][j] = table[i][j-1]+1;
					table[i][j-1] = 0;
				}
			}
		}
	}

	REP(i, h) {
		REP(j, w) {
			if(table[i][j] >= n) {
				FOR(k, j-table[i][j]+1, j) {
					res.push_back(pii(i, k));
				}
			}
		}
	}

	return res;
}

vector<pii> getEraseVerticalPoints(vs field) {
	vector<pii> res;
	vvi table(h, vi(w, 1));
	FOR(i, 1, h-1) {
		REP(j, w) {
			if(field[i][j] != '.') {
				if(field[i][j] == field[i-1][j]) {
					table[i][j] = table[i-1][j]+1;
					table[i-1][j] = 0;
				}
			}
		}
	}

	REP(i, h) {
		REP(j, w) {
			if(table[i][j] >= n) {
				FOR(k, i-table[i][j]+1, i) {
					res.push_back(pii(k, j));
				}
			}
		}
	}

	return res;
}

vector<pii> getErasePoints(vs field) {
	vector<pii> horizontalPoints = getEraseHorizontalPoints(field);
	vector<pii> verticalPoints = getEraseVerticalPoints(field);

	int size = verticalPoints.size();
	REP(i, size) {
		horizontalPoints.push_back(verticalPoints[i]);
	}

	return horizontalPoints;
}

vs erase(vs field, vector<pii> points) {
	int size = points.size();
	REP(i, size) {
		field[points[i].first][points[i].second] = '.';
	}

	return field;
}

vs fallBlocks(vs field) {
	REP(j, w) {
		string blocks = "";
		REP(i, h) {
			if(field[i][j] == '.') {
				int size = blocks.size();
				REP(k, size) {
					field[i-k][j] = blocks[size-k-1];
				}
				field[i-size][j] = '.';
			} else {
				blocks.push_back(field[i][j]);
			}
		}
	}

	return field;
}

vs swapField(vs field, int x, int y) {
	char tmp = field[y][x];
	field[y][x] = field[y][x+1];
	field[y][x+1] = tmp;

	return field;
}

int main() {
	cin >> h >> w >> n;
	vs originField(h);
	REP(i, h) {
		cin >> originField[i];
	}

	REP(i, h) {
		REP(j, w-1) {
			bool updated = true;
			vs field = fallBlocks(swapField(originField, j, i));
			while(updated) {
				updated = false;
				vector<pii> erasePoints = getErasePoints(field);
				if(erasePoints.size() > 0) {
					updated = true;
					field = erase(field, erasePoints);
					field = fallBlocks(field);
				}

				if(isEmptyField(field)) {
					cout << "YES" << endl;
					return 0;
				}
			}
		}
	}

	cout << "NO" << endl;
	return 0;
}

Measured memory_bytes: 1252