#include <iostream>
#include <string>
#define EPS 1e-6
#define MAXN 101
#define zero(x) (((x)>0?(x):-(x))<EPS)
using namespace std;
int DEBUG;
int n, m, num;
struct tree
{
tree *next[52], *fail;
int id, L;
};
struct point
{
double x, y;
void data(int i, int j)
{x = i; y = j;}
void write(){printf("%.0lf %.0lf\n",x, y);}
};
tree *root, *p;
tree arr[1000005];
int indexx;
int map(char ch)
{
if(ch <= 'Z') return ch - 'A';
else return ch - 'a';
}
void newn()
{
arr[indexx].fail = NULL;
arr[indexx].id = 0;
arr[indexx].L = -1;
for(int i = 0; i < 52; i ++) arr[indexx].next[i] = 0;
}
void init()
{
indexx = 0;
newn();
root = &arr[indexx ++];
}
void insert(char ch[], int id, int L)
{
int t, i = 0;
p = root;
while(ch[i])
{
t = map(ch[i]);
if(p->next[t] == 0)
{
newn();
p->next[t] = &arr[indexx ++];
}
p = p->next[t];
i ++;
}
p->L = L - 1;
p->id = id;
}
tree *que[1000005];
void get_fail()
{
int close = -1, open = 0;
p = root; p->fail = root;
que[0] = p;
while(close < open)
{
p = que[++close];
for(int i = 0; i < 52; i ++)
{
if(p->next[i] == 0)
{
if(p == root) p->next[i] = root;
else p->next[i] = p->fail->next[i];
}
else
{
if(p == root) p->next[i]->fail = root;
else p->next[i]->fail = p->fail->next[i];
que[++open] = p->next[i];
}
}
}
}
char list[101][101];
point line[101][2];
int mv[8][2] = {{0, 1}, {1, 0}, {1, 1}, {-1, -1}, {0, -1}, {-1, 0}, {1, -1}, {-1, 1}};
bool ok(int x, int y)
{return x < n && x >= 0 && y < m && y >= 0;}
void query(int inix, int iniy, int way)//way => direction
{
int t, i = 0, x = inix, y = iniy;
tree *q;
p = root;
while( ok(x, y) )
{
t = map(list[x][y]);
while(!p->next[t] && p != root) p = p->fail;
p = p->next[t];
if(!p) p = root; q = p;
while( q != root && q->fail)
{
if(q->id)
{
int i = q->id;
point end;
end.data(x, y);
line[i][1] = end;
point sta;
sta.data(x - q->L * mv[way][0], y - q->L * mv[way][1]);
line[i][0] = sta;
q->id = 0;
}
q = q->fail;
}
i ++;
x += mv[way][0];
y += mv[way][1];
}
}
int tu[101][101];
//计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//判三点共线
int dots_inline(point p1,point p2,point p3){
return zero(xmult(p1,p2,p3));
}
//判点是否在线段上,包括端点
int dot_online_in(point p,point l1,point l2){
return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<EPS&&(l1.y-p.y)*(l2.y-p.y)<EPS;
}
//判两点在线段同侧,点在线段上返回0
int same_side(point p1,point p2,point l1,point l2){
return xmult(l1,p1,l2)*xmult(l1,p2,l2)>EPS;
}
//判两线段相交,包括端点和部分重合
int intersect_in(point u1,point u2,point v1,point v2){
if (!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
return !same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);
return dot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
//计算两直线交点,注意事先判断直线是否平行!
point intersection(point u1,point u2,point v1,point v2){
point ret=u1;
double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
return ret;
}
bool connect(int i, int j)
{
point s1, s2, e1, e2, p;
s1 = line[i][0];
e1 = line[i][1];
s2 = line[j][0];
e2 = line[j][1];
if(intersect_in(s1, e1, s2, e2))
p = intersection(s1, e1, s2, e2);
else return false;
if( p.x - (int)p.x > EPS || p.y - (int)p.y > EPS) return false;
return true;
}
void bulid()
{
int i, j;
memset(tu, 0, sizeof(tu));
//线段相交构图
for(i = 1; i <= num; i ++)
{
for(j = i + 1; j <= num; j ++)
if( connect(i, j) )
{
tu[i][j] = true;
tu[j][i] = true;
}
}
}
int cnt;
bool h[101];
void dfs(int x)
{
int i;
for(i = 1; i <= num; i ++)
if(!h[i] && tu[x][i])
{
h[i] = 1;
cnt ++;
dfs(i);
}
}
void search(int n,int mat[][MAXN],int* dfn,int* low,int now,int& ret,int* key,int& cnt,int root,int& rd,int* bb){
int i;
dfn[now]=low[now]=++cnt;
for (i=1;i<=n;i++)
if (mat[now][i]){
if (!dfn[i]){
search(n,mat,dfn,low,i,ret,key,cnt,root,rd,bb);
if (low[i]<low[now])
low[now]=low[i];
if (low[i]>=dfn[now]){
if (now!=root&&!bb[now])
key[ret++]=now,bb[now]=1;
else if(now==root)
rd++;
}
}
else if (dfn[i]<low[now])
low[now]=dfn[i];
}
}
int key_vertex(int n,int mat[][MAXN],int* key){
int ret=0,i,cnt,rd,dfn[MAXN],low[MAXN],bb[MAXN];
for (i=1;i<=n;dfn[i++]=bb[i]=0);
for (cnt=0,i=1;i<=n;i++)
if (!dfn[i]){
rd=0;
search(n,mat,dfn,low,i,ret,key,cnt,i,rd,bb);
if (rd>1&&!bb[i])
key[ret++]=i,bb[i]=1;
}
return ret;
}
bool solve()
{
//查询
for(int i = 0; i < n; i ++)
for(int J = 0; J < m; J ++)
{
query(i, J, 0); query(i, J, 4);
query(i, J, 1); query(i, J, 5);
query(i, J, 2); query(i, J, 6);
query(i, J, 3); query(i, J, 7);
}
//建图
bulid();
memset(h ,0 ,sizeof(h));
cnt = 1;
h[1] = 1;
//连通性
dfs(1);
if(cnt != num) return false;
int key[101];
//割点
cnt = key_vertex(num, tu, key);
if(cnt > 0) return false;
return true;
}
int main()
{
DEBUG = 0;
freopen("in1.txt","r",stdin);
while(scanf("%d %d %d", &n, &m, &num), n+m+num)
{
for(int i = 0; i < n; i ++) scanf("%s", list[i]);
char temp[101];
//AC自动机
init();
for(int i = 1; i <= num; i ++)
{
scanf("%s", temp);
int l = strlen(temp);
insert(temp, i, l);
}
get_fail();
//构图求解
if(solve()) puts("Yes");
else puts("No");
}
while(1);
}