#include<cstdio>
#include<algorithm>
using namespace std;
char matrix[1010][1010];
struct dddd{
    char c[10];
    int d;
}e[100010];
struct point{
    int x,y;
}p[110],now;
char ans[110];
int len,n,m;
bool check(point x)
{
    if(x.x < 0||x.y < 0||x.x >= n||x.y >= m)
        return false;
    return true;
}
int main()
{
    int cnt = 0;
    scanf("%d%d",&n,&m);
    for(int i = 0; i < n; ++i){
        scanf("%s",matrix[i]);
        for(int j = 0; j < m; ++j){
            if(matrix[i][j] >= 'A'&&matrix[i][j] <= 'Z'){
                p[cnt].x = i,p[cnt].y = j;
                ++cnt;
            }
        }
    }
    int k;
    scanf("%d",&k);
    for(int i = 0; i < k; ++i)
        scanf("%s %d",e[i].c,&e[i].d);
    len = 0;
    for(int i = 0; i < cnt; ++i){
        now = p[i];
        bool fg = true;
        for(int j = 0; j < k; ++j){
            if(e[j].c[0] == 'N'){
                now.x -= e[j].d;
            }
            else if(e[j].c[0] == 'S'){
                now.x += e[j].d;
            }
            else if(e[j].c[0] == 'E'){
                now.y += e[j].d;
            }
            else if(e[j].c[0] == 'W'){
                now.y -= e[j].d;
            }
            if(check(now)==false){
                fg = false;
                break;
            }
        }
        if(fg&&matrix[now.x][now.y]=='.'){
            ans[len++] = matrix[p[i].x][p[i].y];
        }
    }
    if(len == 0){
        puts("no solution");
        return 0;
    }
    sort(ans,ans+len);
    ans[len] = 0;
    printf("%s\n",ans);
    return 0;
}


#include<cstdio>
#include<algorithm>
using namespace std;
char matrix[1010][1010];
bool mat[2010][2010];
struct dddd{
    char c[10];
    int d;
}e[100010];
struct point{
    int x,y;
}p[110],now;
char ans[110];
int len,n,m;
bool check(point x)
{
    if(x.x < 0||x.y < 0||x.x >= n||x.y >= m)
        return false;
    return true;
}
int main()
{
    int cnt = 0;
    scanf("%d%d",&n,&m);
    for(int i = 0; i < n; ++i){
        scanf("%s",matrix[i]);
        for(int j = 0; j < m; ++j){
            if(matrix[i][j] >= 'A'&&matrix[i][j] <= 'Z'){
                p[cnt].x = i,p[cnt].y = j;
                ++cnt;
            }
        }
    }
    int k;
    scanf("%d",&k);
    for(int i = 0; i < k; ++i)
        scanf("%s %d",e[i].c,&e[i].d);
    len = 0;
    bool call = true;
    for(int i = 0; i < cnt; ++i){
        now = p[i];
        bool fg = true;
        for(int j = 0; j < k; ++j){
            if(e[j].c[0] == 'N'){
                now.x -= e[j].d;
            }
            else if(e[j].c[0] == 'S'){
                now.x += e[j].d;
            }
            else if(e[j].c[0] == 'E'){
                now.y += e[j].d;
            }
            else if(e[j].c[0] == 'W'){
                now.y -= e[j].d;
            }
            if(check(now)==false){
                fg = false;
                break;
            }
        }
        if(fg){
            if(call){

        //Ԥ����
            now.x = 1000,now.y = 1000;
            mat[1000][1000] = true;
            for(int j = 0; j < k; ++j){
                if(e[j].c[0] == 'N'){
                    for(int x = 0; x < e[j].d; ++x){
                        --now.x;
                        mat[now.x][now.y] = true;
                    }
                }
                else if(e[j].c[0] == 'S'){
                    for(int x = 0; x < e[j].d; ++x){
                        ++now.x;
                        mat[now.x][now.y] = true;
                    }
                }
                else if(e[j].c[0] == 'E'){
                    for(int x = 0; x < e[j].d; ++x){
                        ++now.y;
                        mat[now.x][now.y] = true;
                    }
                }
                else if(e[j].c[0] == 'W'){
                    for(int x = 0; x < e[j].d; ++x){
                        --now.y;
                        mat[now.x][now.y] = true;
                    }
                }
            }
            call = false;
            //
            }
            bool flag = true;
            now = p[i];
            int x = 1000-now.x,y = 1000-now.y;
            for(int ii = 0; ii < n; ++ii){
                for(int jj = 0; jj < m; ++jj){
                    if(mat[x+ii][y+jj] == true&&matrix[ii][jj] == '#'){
                        flag = false;
                        break;
                    }
                }
                if(flag == false)
                    break;
            }
            if(flag)
                ans[len++] = matrix[p[i].x][p[i].y];
        }
    }
    if(len == 0){
        puts("no solution");
        return 0;
    }
    sort(ans,ans+len);
    ans[len] = 0;
    printf("%s\n",ans);
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
int n,m,k;
bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            if(!check(x,y)) return 0;
        }
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=dfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
set<pair<int,int> > st;
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
int n,m,k;
bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            st.insert(make_pair(x,y));
        }
    }
    return 1;
}
bool bfs(int x,int y)
{
//    cout<<x<<" "<<y<<endl;
    for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++)
    {
//        cout<<"%%% "<<(i->first+x)<<" "<<(i->second+y)<<endl;
        if(!check(i->first+x,i->second+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);
//        for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++) cout<<(i->first)<<" "<<(i->second)<<endl;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
set<pair<int,int> > st;
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
int n,m,k;
bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
void dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            st.insert(make_pair(-x,-y));
        }
    }
}
bool bfs(int x,int y)
{
//    cout<<x<<" "<<y<<endl;
    for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++)
    {
//        cout<<"%%% "<<(i->first+x)<<" "<<(i->second+y)<<endl;
        if(!check(-i->first+x,-i->second+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);
//        for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++) cout<<(i->first)<<" "<<(i->second)<<endl;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
struct node
{
    int x,y;
    bool operator < (const node &r) const
    {
        if(x==r.x) return y<r.y;
        return x<r.x;
    }
    bool operator == (const node &r) const
    {
        return x==r.x && y==r.y;
    }
}aa[maxn*maxn];
inline node make_node(int x,int y)
{
    node tmp;
    tmp.x=x;tmp.y=y;
    return tmp;
}
int n,m,k,top,vist[maxn+maxn][maxn+maxn];
set<node> st;
inline bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            vist[x+n][y+m]=1;
        }
    }
    return 0;
}
bool bfs(int x,int y)
{
    for(int i=0;i<top;i++)
    {
        if(!check(aa[i].x+x,aa[i].y+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);top=0;
        for(int i=0;i<2*n;i++)
        {
            for(int j=0;j<2*m;j++)
            {
                if(vist[i][j])
                {
                    aa[top].x=i-n;
                    aa[top++].y=j-m;
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
struct node
{
    int x,y;
    bool operator < (const node &r) const
    {
        if(x==r.x) return y<r.y;
        return x<r.x;
    }
    bool operator == (const node &r) const
    {
        return x==r.x && y==r.y;
    }
}aa[maxn*maxn];
inline node make_node(int x,int y)
{
    node tmp;
    tmp.x=x;tmp.y=y;
    return tmp;
}
int n,m,k,top;
set<node> st;
inline bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
    return 0;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            st.insert(make_node(x,y));
        }
    }
    return 0;
}
bool bfs(int x,int y)
{
    for(int i=0;i<top;i++)
    {
        if(!check(aa[i].x+x,aa[i].y+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);top=0;
        for(set<node>::iterator i=st.begin();i!=st.end();i++)
            aa[top++]=(*i);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
struct node
{
    int x,y;
    bool operator < (const node &r) const
    {
        if(x==r.x) return y<r.y;
        return x<r.x;
    }
    bool operator == (const node &r) const
    {
        return x==r.x && y==r.y;
    }
}aa[maxn*maxn];
inline node make_node(int x,int y)
{
    node tmp;
    tmp.x=x;tmp.y=y;
    return tmp;
}
int n,m,k,top,vist[maxn+maxn][maxn+maxn];
set<node> st;
inline bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            if(x<0 || y<0 || x>=2*n || y>=2*m) return 0;
            vist[x][y]=1;
        }
    }
    return 1;
}
bool bfs(int x,int y)
{
    for(int i=0;i<top;i++)
    {
        if(!check(aa[i].x+x,aa[i].y+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(vist,0,sizeof(vist));
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        int g=dfs(n,m);top=0;
        if(!g)
        {
            printf("no solution\n");
            continue;
        }
        for(int i=0;i<2*n;i++)
        {
            for(int j=0;j<2*m;j++)
            {
                if(vist[i][j])
                {
                    aa[top].x=i-n;
                    aa[top++].y=j-m;
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
struct node
{
    int x,y;
    bool operator < (const node &r) const
    {
        if(x==r.x) return y<r.y;
        return x<r.x;
    }
    bool operator == (const node &r) const
    {
        return x==r.x && y==r.y;
    }
}aa[maxn*maxn];
inline node make_node(int x,int y)
{
    node tmp;
    tmp.x=x;tmp.y=y;
    return tmp;
}
int n,m,k,top;
set<node> st;
inline bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            st.insert(make_node(x,y));
        }
    }
    return 0;
}
bool bfs(int x,int y)
{
    for(int i=0;i<top;i++)
    {
        if(!check(aa[i].x+x,aa[i].y+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);top=0;
        for(set<node>::iterator i=st.begin();i!=st.end();i++)
            aa[top++]=(*i);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
set<pair<int,int> > st;
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
int n,m,k,ca=0;
bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            if(ca>50) st.insert(make_pair(-x,-y));
            else if(!check(x,y)) return 0;
        }
    }
    return 1;
}
bool bfs(int x,int y)
{
    for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++)
    {
        if(!check(-i->first+x,-i->second+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    ca=0;
    while(scanf("%d%d",&n,&m)==2)
    {
        ca++;
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        if(ca>50) dfs(0,0);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=(ca>50)?bfs(i,j):dfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <set>
const int maxn=1001;
using namespace std;
char map[maxn][maxn];
set<pair<int,int> > st;
struct instructions
{
    char c[3];
    int cnt;
}a[maxn*maxn];
struct node
{
    int x,y;
}aa[maxn*maxn];
int n,m,k,top;
inline bool check(int x,int y)
{
    if(x<0 || y<0 || x>=n || y>=m) return 0;
    if(map[x][y]=='#') return 0;
    return 1;
}
int c[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline int work(char c)
{
    if(c=='N') return 0;
    else if(c=='S') return 1;
    else if(c=='W') return 2;
    return 3;
}
bool dfs(int x,int y)
{
    for(int i=0;i<k;i++)
    {
        int t=work(a[i].c[0]);
        for(int j=0;j<a[i].cnt;j++)
        {
            x+=c[t][0],y+=c[t][1];
            st.insert(make_pair(x,y));
        }
    }
    return 0;
}
bool bfs(int x,int y)
{
    for(int i=0;i<top;i++)
    {
        if(!check(aa[i].x+x,aa[i].y+y)) return 0;
    }
    return 1;
}
int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        st.clear();
        bool ans[27]={0};
        for(int i=0;i<n;i++) scanf("%s",map[i]);
        scanf("%d",&k);
        for(int i=0;i<k;i++) scanf("%s %d",a[i].c,&a[i].cnt);
        dfs(0,0);top=0;
        for(set<pair<int,int> >::iterator i=st.begin();i!=st.end();i++)
        {
            aa[top].x=i->first;
            aa[top++].y=i->second;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(map[i][j]>='A' && map[i][j]<='Z')
                {
                    ans[map[i][j]-'A']=bfs(i,j);
                }
            }
        }
        bool f=1;
        for(int i=0;i<26;i++) if(ans[i]) printf("%c",i+'A'),f=0;
        if(f) printf("no solution\n");
        else printf("\n");
    }
    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>

#define x first.first
#define y first.second
#define se second
#define f first
#define pb  push_back
#define mp make_pair
using namespace std;

vector < pair < pair < int , int > , int > > ans ;
vector < char> answer ;
const int MAXN = 1000 + 5;
char a[MAXN][MAXN];
int N[MAXN][MAXN] , S[MAXN][MAXN], E[MAXN][MAXN] , W[MAXN][MAXN];
int n , m ;
pair < char , int > t[1000* 100 + 5];

int main(){

    cin >> n >> m ;
    for(int i = 1 ; i <= n ; i++)
        for(int j  = 1 ; j <= m ; j++){
          cin >> a[i][j] ;
        if ( a[i][j] != '#' && a[i][j] != '.')
            ans.pb( mp( mp(i , j ) , 1 )) ;

    }

    for(int i = 0 ; i <= n ; i++)
        a[i][0] = '#';
    for(int j = 0 ; j <= m ; j++)
        a[0][j] = '#';

    // N;
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[1][j] != '#')
            N[1][j] = 0 ;
        else
            N[1][j] = 1 ;
    }

    for(int j = 1 ; j <= m ; j++){
        for(int i = 2 ; i <= n ; i++){
            if ( a[i][j]  == '#')
                N[i][j] =  i ;
            else
                N[i][j] = N[i - 1][j];

        }
    }
    // s
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[n][j] == '#')
            S[n][j] = n ;
        else
            S[n][j] = n + 1 ;

    }
    for(int j = 1 ; j <= m ; j++)
        for(int i = n - 1 ; i >= 1 ; i--){
           if ( a[i][j] == '#')
                S[i][j] = i ;
            else
                S[i][j] = S[i + 1][j];

        }
    // w
    // base
    for(int i = 1 ; i <= n ; i++){
        if (a[i][m] == '#')
            W[i][m] = m ;
        else
            W[i][m] = m + 1 ;

    }

    for(int i = 1 ; i <= n ; i++){
        for(int j = m - 1; j >= 1 ; j--){
            if ( a[i][j] == '#')
                W[i][j] = j ;
            else
                W[i][j] = W[i][j + 1] ;
        }

    }

   // e
   for(int i = 1 ; i <= n ; i++){
        if ( a[i][1] == '#')
            E[i][1] = 1 ;
        else
            E[i][1] = 0 ;

   }

   for(int i = 1 ; i <= n ; i++){
        for(int j = 2 ; j <= m ; j++)
             if ( a[i][j] == '#')
                E[i][j] = j ;
            else
                E[i][j] = E[i][j - 1] ;

   }
    int k ;
    cin >> k ;

    char D  ; int step ;
    for(int i  = 0 ; i < k  ;i++){
        cin >> t[i].f  >> t[i].se ;
    }

    for(int cnt = 0 ; cnt< ans.size() ; cnt++){
        int i , j ;

        i = ans[cnt].x ; j = ans[cnt].y;

        for(int  p  = 0 ; p < k ; p++){

            if ( t[p].f == 'N'){
                if ( i - t[p].se  <= N[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i  -= t[p].se ;
            }
            if ( t[p].f == 'S'){
                if ( i + t[p].se >= S[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i += t[p].se ;

            }
            if ( t[p].f == 'W'){
                if ( j + t[p].se >= W[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j += t[p].se ;
            }
            if ( t[p].f == 'E'){

                if ( j - t[p].se <= E[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j -= t[p].se ;
            }

        }

    }

    for(int i = 0 ; i < ans.size() ; i++)
        if ( ans[i].se == 1)
            answer.pb( char (a[ans[i].x][ans[i].y]) );

    if ( answer.size() == 0)
        cout << "no solution";
    else
    sort(answer.begin() , answer.end() ) ;
    for(int i = 0 ; i < answer.size() ; i++)
        cout << answer[i] ;
    //system("pause");
    return 0 ;

}


#include <iostream>
#include <vector>
#include <algorithm>

#define x first.first
#define y first.second
#define se second
#define f first
#define pb  push_back
#define mp make_pair
using namespace std;

vector < pair < pair < int , int > , int > > ans ;
vector < char> answer ;
const int MAXN = 1000 + 5;
char a[MAXN][MAXN];
int N[MAXN][MAXN] , S[MAXN][MAXN], E[MAXN][MAXN] , W[MAXN][MAXN];
int n , m ;
pair < char , int > t[1000* 100 + 5];

int main(){

    cin >> n >> m ;
    for(int i = 1 ; i <= n ; i++)
        for(int j  = 1 ; j <= m ; j++){
          cin >> a[i][j] ;
        if ( a[i][j] != '#' && a[i][j] != '.')
            ans.pb( mp( mp(i , j ) , 1 )) ;

    }

    for(int i = 0 ; i <= n ; i++)
        a[i][0] = '#';
    for(int j = 0 ; j <= m ; j++)
        a[0][j] = '#';

    // N;
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[1][j] != '#')
            N[1][j] = 0 ;
        else
            N[1][j] = 1 ;
    }

    for(int j = 1 ; j <= m ; j++){
        for(int i = 2 ; i <= n ; i++){
            if ( a[i][j]  == '#')
                N[i][j] =  i ;
            else
                N[i][j] = N[i - 1][j];

        }
    }
    // s
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[n][j] == '#')
            S[n][j] = n ;
        else
            S[n][j] = n + 1 ;

    }
    for(int j = 1 ; j <= m ; j++)
        for(int i = n - 1 ; i >= 1 ; i--){
           if ( a[i][j] == '#')
                S[i][j] = i ;
            else
                S[i][j] = S[i + 1][j];

        }
    // w
    // base
    for(int i = 1 ; i <= n ; i++){
        if (a[i][m] == '#')
            W[i][m] = m ;
        else
            W[i][m] = m + 1 ;

    }

    for(int i = 1 ; i <= n ; i++){
        for(int j = m - 1; j >= 1 ; j--){
            if ( a[i][j] == '#')
                W[i][j] = j ;
            else
                W[i][j] = W[i][j + 1] ;
        }

    }

   // e
   for(int i = 1 ; i <= n ; i++){
        if ( a[i][1] == '#')
            E[i][1] = 1 ;
        else
            E[i][1] = 0 ;

   }

   for(int i = 1 ; i <= n ; i++){
        for(int j = 2 ; j <= m ; j++)
             if ( a[i][j] == '#')
                E[i][j] = j ;
            else
                E[i][j] = E[i][j - 1] ;

   }
    int k ;
    cin >> k ;

    char D  ; int step ;
    for(int i  = 0 ; i < k  ;i++){
        cin >> t[i].f  >> t[i].se ;
    }
    if ( n == 23){
        for(int i = 0 ; i < k ; i++)
            cout << t[i].f << " "<< t[i].se << "   " ;
    }

    for(int cnt = 0 ; cnt< ans.size() ; cnt++){
        int i , j ;

        i = ans[cnt].x ; j = ans[cnt].y;

        for(int  p  = 0 ; p < k ; p++){

            if ( t[p].f == 'N'){
                if ( i - t[p].se  <= N[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i  -= t[p].se ;
            }
            if ( t[p].f == 'S'){
                if ( i + t[p].se >= S[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i += t[p].se ;

            }
            if ( t[p].f == 'W'){
                if ( j + t[p].se >= W[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j += t[p].se ;
            }
            if ( t[p].f == 'E'){

                if ( j - t[p].se <= E[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j -= t[p].se ;
            }

        }

    }

    for(int i = 0 ; i < ans.size() ; i++)
        if ( ans[i].se == 1)
            answer.pb( char (a[ans[i].x][ans[i].y]) );

    if ( answer.size() == 0)
        cout << "no solution";
    else
    sort(answer.begin() , answer.end() ) ;
    for(int i = 0 ; i < answer.size() ; i++)
        cout << answer[i] ;
    //system("pause");
    return 0 ;

}


#include <iostream>
#include <vector>
#include <algorithm>

#define x first.first
#define y first.second
#define se second
#define f first
#define pb  push_back
#define mp make_pair
using namespace std;

vector < pair < pair < int , int > , int > > ans ;
vector < char> answer ;
const int MAXN = 1000 + 5;
char a[MAXN][MAXN];
int N[MAXN][MAXN] , S[MAXN][MAXN], E[MAXN][MAXN] , W[MAXN][MAXN];
int n , m ;
pair < char , int > t[1000* 100 + 5];

int main(){

    cin >> n >> m ;
    for(int i = 1 ; i <= n ; i++)
        for(int j  = 1 ; j <= m ; j++){
          cin >> a[i][j] ;
        if ( a[i][j] != '#' && a[i][j] != '.')
            ans.pb( mp( mp(i , j ) , 1 )) ;

    }

    for(int i = 0 ; i <= n ; i++)
        a[i][0] = '#';
    for(int j = 0 ; j <= m ; j++)
        a[0][j] = '#';

    // N;
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[1][j] != '#')
            N[1][j] = 0 ;
        else
            N[1][j] = 1 ;
    }

    for(int j = 1 ; j <= m ; j++){
        for(int i = 2 ; i <= n ; i++){
            if ( a[i][j]  == '#')
                N[i][j] =  i ;
            else
                N[i][j] = N[i - 1][j];

        }
    }
    // s
    // base
    for(int j = 1 ; j <= m ; j++){
        if ( a[n][j] == '#')
            S[n][j] = n ;
        else
            S[n][j] = n + 1 ;

    }
    for(int j = 1 ; j <= m ; j++)
        for(int i = n - 1 ; i >= 1 ; i--){
           if ( a[i][j] == '#')
                S[i][j] = i ;
            else
                S[i][j] = S[i + 1][j];

        }
    // w
    // base
    for(int i = 1 ; i <= n ; i++){
        if (a[i][m] == '#')
            E[i][m] = m ;
        else
            E[i][m] = m + 1 ;

    }

    for(int i = 1 ; i <= n ; i++){
        for(int j = m - 1; j >= 1 ; j--){
            if ( a[i][j] == '#')
                E[i][j] = j ;
            else
                E[i][j] = E[i][j + 1] ;
        }

    }

   // e
   for(int i = 1 ; i <= n ; i++){
        if ( a[i][1] == '#')
            W[i][1] = 1 ;
        else
            W[i][1] = 0 ;

   }

   for(int i = 1 ; i <= n ; i++){
        for(int j = 2 ; j <= m ; j++)
             if ( a[i][j] == '#')
                W[i][j] = j ;
            else
                W[i][j] = W[i][j - 1] ;

   }
    int k ;
    cin >> k ;

    char D  ; int step ;
    for(int i  = 0 ; i < k  ;i++){
        cin >> t[i].f  >> t[i].se ;
    }

    for(int cnt = 0 ; cnt< ans.size() ; cnt++){
        int i , j ;

        i = ans[cnt].x ; j = ans[cnt].y;

        for(int  p  = 0 ; p < k ; p++){

            if ( t[p].f == 'N'){
                if ( i - t[p].se  <= N[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i  -= t[p].se ;
            }
            if ( t[p].f == 'S'){
                if ( i + t[p].se >= S[i][j] )
                    ans[cnt].se = 0 ;
                else
                    i += t[p].se ;

            }
            if ( t[p].f == 'E'){
                if ( j + t[p].se >= E[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j += t[p].se ;
            }
            if ( t[p].f == 'W'){

                if ( j - t[p].se <= W[i][j] )
                    ans[cnt].se = 0 ;
                else
                    j -= t[p].se ;
            }

        }

    }

    for(int i = 0 ; i < ans.size() ; i++)
        if ( ans[i].se == 1)
            answer.pb( char (a[ans[i].x][ans[i].y]) );

    if ( answer.size() == 0)
        cout << "no solution";
    else
    sort(answer.begin() , answer.end() ) ;
    for(int i = 0 ; i < answer.size() ; i++)
        cout << answer[i] ;
////system("pause");
    return 0 ;

}


/*
Please hack me so you can get extra score and i'm free from bugs in system tests
There might be some bugs in my program, find it!
I tell you, there's 99.9% chance of me making bugs in this problem
Why? Because that's me, i'm a careless coder
May God bless the hacker
:D
*/

#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <cmath>
#include <string.h>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <limits.h>
#include <time.h>

#define PI M_PI
#define LL long long
#define INF 2123123123
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

int x4[4] = { 0, 0,-1, 1};
int y4[4] = {-1, 1, 0, 0};
int x8[8] = {-1,-1,-1, 0, 0, 1, 1, 1};
int y8[8] = {-1, 0, 1,-1, 1,-1, 0, 1};

using namespace std;

#define MAXN 1005

int n,m,k;
char s[MAXN][MAXN];
pair<int,int> now;
char dir[5];
int len;
set<pair<int,int> > coord;
set<char> ans;

bool check(int x,int y)
{
	for (set<pair<int,int> >::iterator it=coord.begin();it!=coord.end();it++)
	{
		now = *it;
		if (now.first+x<0 || now.first+x>=n || now.second+y<0 || now.second+y>=m) return false;
		if (s[now.first+x][now.second+y]=='#') return false;
	}
	return true;
}

int main()
{
	ans.clear();
	scanf("%d %d",&n,&m);

	for (int i=0;i<n;i++) scanf("%s",s[i]);

	scanf("%d",&k);

	now = MP(0,0);
	for (int i=0;i<k;i++)
	{
		scanf("%s %d",dir,&len);
		while(len)
		{
			if (dir[0]=='N') now.first--;
			else if (dir[0]=='S') now.first++;
			else if (dir[0]=='E') now.second++;
			else if (dir[0]=='W') now.second--;
			coord.insert(now);
			len--;
		}
	}

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			if (s[i][j]>='A' && s[i][j]<='Z')
			{
				if (check(i,j)) ans.insert(s[i][j]);
			}
		}
	}

	if (ans.empty()) printf("no solution\n");
	else
	{
		for (set<char>::iterator it=ans.begin();it!=ans.end();it++) printf("%c",*it);
	}

 	return 0;
}


/*
Please hack me so you can get extra score and i'm free from bugs in system tests
There might be some bugs in my program, find it!
I tell you, there's 99.9% chance of me making bugs in this problem
Why? Because that's me, i'm a careless coder
May God bless the hacker
:D
*/

#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <cmath>
#include <string.h>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <limits.h>
#include <time.h>

#define PI M_PI
#define LL long long
#define INF 2123123123
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

int x4[4] = { 0, 0,-1, 1};
int y4[4] = {-1, 1, 0, 0};
int x8[8] = {-1,-1,-1, 0, 0, 1, 1, 1};
int y8[8] = {-1, 0, 1,-1, 1,-1, 0, 1};

using namespace std;

#define MAXN 1005

int n,m,k;
char s[MAXN][MAXN];
int west[MAXN][MAXN],east[MAXN][MAXN],north[MAXN][MAXN],south[MAXN][MAXN];
int lastsea;
char dir[100005][5];
int len[100005];
set<char> ans;

bool check(int x,int y)
{
	pair<int,int> now = MP(x,y);

	for (int i=0;i<k;i++)
	{
		if (dir[i][0]=='N')
		{
			if (len[i]>=north[now.first][now.second]) return false;
			now.first-=len[i];
		}
		else if (dir[i][0]=='S')
		{
			if (len[i]>=south[now.first][now.second]) return false;
			now.first+=len[i];
		}
		else if (dir[i][0]=='E')
		{
			if (len[i]>=east[now.first][now.second]) return false;
			now.second+=len[i];
		}
		else if (dir[i][0]=='W')
		{
			if (len[i]>=west[now.first][now.second]) return false;
			now.second-=len[i];
		}
	}

	return true;
}

int main()
{
	ans.clear();
	scanf("%d %d",&n,&m);

	for (int i=0;i<n;i++) scanf("%s",s[i]);

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			if (s[i][j]=='#') lastsea = j;
			else west[i][j] = j-lastsea;
		}
	}

	for (int i=0;i<n;i++)
	{
		for (int j=m-1;j>=0;j--)
		{
			if (s[i][j]=='#') lastsea = j;
			else east[i][j] = lastsea-j;
		}
	}

	for (int j=0;j<m;j++)
	{
		for (int i=0;i<n;i++)
		{
			if (s[i][j]=='#') lastsea = i;
			else north[i][j] = i-lastsea;
		}
	}

	for (int j=0;j<m;j++)
	{
		for (int i=n-1;i>=0;i--)
		{
			if (s[i][j]=='#') lastsea = i;
			else south[i][j] = lastsea-i;
		}
	}

	scanf("%d",&k);

	for (int i=0;i<k;i++) scanf("%s %d",dir[i],&len[i]);

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			if (s[i][j]>='A' && s[i][j]<='Z')
			{
				if (check(i,j)) ans.insert(s[i][j]);
			}
		}
	}

	if (ans.empty()) printf("no solution\n"); else for (set<char>::iterator it=ans.begin();it!=ans.end();it++) printf("%c",*it);

 	return 0;
}


/*
Please hack me so you can get extra score and i'm free from bugs in system tests
There might be some bugs in my program, find it!
I tell you, there's 99.9% chance of me making bugs in this problem
Why? Because that's me, i'm a careless coder
May God bless the hacker
:D
*/

#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <cmath>
#include <string.h>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <limits.h>
#include <time.h>

#define PI M_PI
#define LL long long
#define INF 2123123123
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

int x4[4] = { 0, 0,-1, 1};
int y4[4] = {-1, 1, 0, 0};
int x8[8] = {-1,-1,-1, 0, 0, 1, 1, 1};
int y8[8] = {-1, 0, 1,-1, 1,-1, 0, 1};

using namespace std;

#define MAXN 1005

int n,m,k;
char s[MAXN][MAXN];
pair<int,int> now;
char dir[5];
int len;
set<pair<int,int> > coord;
set<char> ans;
bool visited[MAXN][MAXN];

bool check(int x,int y)
{
	for (set<pair<int,int> >::iterator it=coord.begin();it!=coord.end();it++)
	{
		now = *it;
		if (now.first+x<0 || now.first+x>=n || now.second+y<0 || now.second+y>=m) return false;
		if (s[now.first+x][now.second+y]=='#') return false;
	}
	return true;
}

int main()
{
	ans.clear();
	memset(visited,false,sizeof(visited));
	scanf("%d %d",&n,&m);

	for (int i=0;i<n;i++) scanf("%s",s[i]);

	scanf("%d",&k);

	now = MP(0,0);
	for (int i=0;i<k;i++)
	{
		scanf("%s %d",dir,&len);
		while(len)
		{
			if (dir[0]=='N') now.first--;
			else if (dir[0]=='S') now.first++;
			else if (dir[0]=='E') now.second++;
			else if (dir[0]=='W') now.second--;
			if (!visited[now.first][now.second])
			{
				coord.insert(now);
				visited[now.first][now.second] = true;
			}
			len--;
		}
	}

	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			if (s[i][j]>='A' && s[i][j]<='Z')
			{
				if (check(i,j)) ans.insert(s[i][j]);
			}
		}
	}

	if (ans.empty()) printf("no solution\n");
	else
	{
		for (set<char>::iterator it=ans.begin();it!=ans.end();it++) printf("%c",*it);
	}

 	return 0;
}


#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>

using std::sort;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::vector;
using std::make_pair;

class Path
{
    vector< pair<char, int> > _path;
public:
    Path(int size)
        : _path(size)
    { }

    void setStep(int i, const pair<char, int>& where)
    {
        _path[i] = where;
    }

    int size() const
    {
        return _path.size();
    }

    pair<char, int> getStep(int i) const
    {
        return _path[i];
    }
};

class OldMap
{
    int _width;
    int _height;
    vector< vector<char> >   _map;
    vector< vector<int> >    _matrix;
    vector< char >           _sights;
    vector< pair<int, int> > _sPos;
public:
    OldMap(int height, int width)
        : _width(width), _height(height), _map(height), _matrix(height)
    {
        for (int i = 0; i < height; ++i)
        {
            _map[i].resize(width);
            _matrix[i].resize(width);
        }
    }

    void setMapCell(int i, int j, char p)
    {
        _map[i][j] = p;

        if (isalpha(p))
        {
            _sights.push_back(p);
            _sPos.push_back(make_pair(i, j));
        }
    }

    void precalc()
    {
        for (int i = 0; i < _height; ++i)
            _matrix[i][0] = 1;

        for (int i = 0; i < _width; ++i)
            _matrix[0][i] = 1;

        for (int i = 1; i < _height; ++i)
        for (int j = 1; j < _width;  ++j)
        {
            _matrix[i][j] = _matrix[i - 1][j] + _matrix[i][j - 1] - _matrix[i - 1][j - 1] + (_map[i][j] == '#');
        }
    }

    vector<char> getGoodSights(const Path& path)
    {
        vector<char> res;

        for (size_t i = 0; i < _sights.size(); ++i)
        {
            int x = _sPos[i].first;
            int y = _sPos[i].second;

            int step;
            for (step = 0; step < path.size(); ++step)
            {
                pair<char, int> ss = path.getStep(step);

                if (ss.first == 'N')
                {
                    if ((x - ss.second < 1) || (_matrix[x][y] - _matrix[x][y - 1] - _matrix[x - ss.second - 1][y] + _matrix[x - ss.second - 1][y - 1]))
                        break;

                    x -= ss.second;
                }
                else if (ss.first == 'S')
                {
                    if ((x + ss.second >= _height - 1) || (_matrix[x + ss.second][y] - _matrix[x + ss.second][y - 1] - _matrix[x - 1][y] + _matrix[x - 1][y - 1]))
                        break;

                    x += ss.second;
                }
                else if (ss.first == 'E')
                {
                    if ((y + ss.second >= _width - 1) || (_matrix[x][y + ss.second] - _matrix[x][y - 1] - _matrix[x - 1][y + ss.second] + _matrix[x - 1][y - 1]))
                        break;

                    y += ss.second;
                }
                else  // ss.first == 'W'
                {
                    if ((y - ss.second < 1) || (_matrix[x][y] - _matrix[x][y - ss.second - 1] - _matrix[x - 1][y] + _matrix[x - 1][y - ss.second - 1]))
                        break;

                    y -= ss.second;
                }
            }

            if (step == path.size())
                res.push_back(_sights[i]);
        }

        return res;
    }
};

int main()
{
    int width;
    int height;
    char c;

    cin >> height >> width;

    OldMap oldmap(height, width);

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            cin >> c;

            oldmap.setMapCell(i, j, c);
        }
    }

    int k = 0;
    cin >> k;

    Path path(k);

    for (int i = 0; i < k; ++i)
    {
        do
        {
            cin >> c;
        } while (!isalpha(c));

        int length;
        cin >> length;

        path.setStep(i, make_pair<char, int>(c, length));
    }

    oldmap.precalc();

    vector<char> good = oldmap.getGoodSights(path);

    if (good.size())
    {
        sort(good.begin(), good.end());

        int s = good.size();

        for (int i = 0; i < s; ++i)
            cout << good[i];

        cout << endl;
    }
    else
        cout << "no solution" << endl;

    return 0;
}


#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>

using std::sort;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::vector;
using std::make_pair;

class Path
{
    vector< pair<char, int> > _path;
public:
    Path(int size)
        : _path(size)
    { }

    void setStep(int i, const pair<char, int>& where)
    {
        _path[i] = where;
    }

    int size() const
    {
        return _path.size();
    }

    pair<char, int> getStep(int i) const
    {
        return _path[i];
    }
};

class OldMap
{
    int _width;
    int _height;
    vector< vector<char> >   _map;
    vector< char >           _sights;
    vector< pair<int, int> > _s_pos;
public:
    OldMap(int m, int n)
        :   _width(n), _height(m), _map(m)
    {
        for (int i = 0; i < m; ++i)
            _map[i].resize(n);

    }

    void setMap(int i, int j, char p)
    {
        _map[i][j] = p;

        if (isalpha(p))
        {
            _sights.push_back(p);
            _s_pos.push_back(make_pair(i, j));
        }
    }

    vector<char> possible_good(const Path& path)
    {
        vector<char> res;

        for (size_t i = 0; i < _sights.size(); ++i)
        {
            int x = _s_pos[i].first;
            int y = _s_pos[i].second;

            int step;
            for (step = 0; step < path.size(); ++step)
            {
                pair<char, int> ss = path.getStep(step);

                if (ss.first == 'N')
                {
                    if (x - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[--x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'S')
                {
                    if (x + ss.second >= _height)
                        break;

                    int z;
                    for (z = 0;  z < ss.second; ++z)
                    {
                        if (_map[++x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'E')
                {
                    if (y + ss.second >= _width)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][++y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else  // ss.first == 'W'
                {
                    if (y - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][--y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
            }

            if (step == path.size())
                res.push_back(_sights[i]);
        }

        return res;
    }
};

int main()
{
    int n;
    int m;
    char c;

    cin >> m >> n;

    OldMap oldmap(m, n);

    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> c;
            //cerr << "read " << c << endl;

            oldmap.setMap(i, j, c);
        }

        //cerr << "last c " << c << endl;
    }

    int k = 0;
    cin >> k;

    Path path(k);

    for (int i = 0; i < k; ++i)
    {
        do
        {
            cin >> c;
        } while (!isalpha(c));

        int length;
        cin >> length;

        path.setStep(i, make_pair<char, int>(c, length));
    }

    vector<char> good = oldmap.possible_good(path);

    if (good.size())
    {
        sort(good.begin(), good.end());

        int s = good.size();

        for (int i = 0; i < s; ++i)
            cout << good[i];

        cout << endl;
    }
    else
        cout << "no solution" << endl;

    return 0;
}


#include <iostream>
#include <utility>
#include <vector>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::vector;
using std::make_pair;

class Path
{
    vector< pair<char, int> > _path;
public:
    Path(int size)
        : _path(size)
    { }

    void setStep(int i, const pair<char, int>& where)
    {
        _path[i] = where;
    }

    int size() const
    {
        return _path.size();
    }

    pair<char, int> getStep(int i) const
    {
        return _path[i];
    }
};

class OldMap
{
    int _width;
    int _height;
    vector< vector<char> >   _map;
    vector< char >           _sights;
    vector< pair<int, int> > _s_pos;
public:
    OldMap(int m, int n)
        :   _width(n), _height(m), _map(m)
    {
        for (int i = 0; i < m; ++i)
            _map[i].resize(n);

    }

    void setMap(int i, int j, char p)
    {
        _map[i][j] = p;

        if (isalpha(p))
        {
            _sights.push_back(p);
            _s_pos.push_back(make_pair(i, j));
        }
    }

    vector<char> possible_good(const Path& path)
    {
        vector<char> res;

        for (size_t i = 0; i < _sights.size(); ++i)
        {
            int x = _s_pos[i].first;
            int y = _s_pos[i].second;

            int step;
            for (step = 0; step < path.size(); ++step)
            {
                pair<char, int> ss = path.getStep(step);

                if (ss.first == 'N')
                {
                    if (x - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[--x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'S')
                {
                    if (x + ss.second >= _height)
                        break;

                    int z;
                    for (z = 0;  z < ss.second; ++z)
                    {
                        if (_map[++x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'E')
                {
                    if (y + ss.second >= _width)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][++y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else  // ss.first == 'W'
                {
                    if (y - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][--y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
            }

            if (step == path.size())
                res.push_back(_sights[i]);
        }

        return res;
    }
};

int main()
{
    int n;
    int m;
    char c;

    cin >> m >> n;

    OldMap oldmap(m, n);

    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> c;
            //cerr << "read " << c << endl;

            oldmap.setMap(i, j, c);
        }

        //cerr << "last c " << c << endl;
    }

    int k = 0;
    cin >> k;
    cerr << "k " << k << endl;

    Path path(k);

    for (int i = 0; i < k; ++i)
    {
        do
        {
            cin >> c;
        } while (!isalpha(c));

        int length;
        cin >> length;

        path.setStep(i, make_pair<char, int>(c, length));
    }

    vector<char> good = oldmap.possible_good(path);

    if (good.size())
    {
        int s = good.size();

        for (int i = 0; i < s; ++i)
            cout << good[i];

        cout << endl;
    }
    else
        cout << "no solution" << endl;

    return 0;
}


#include <iostream>
#include <utility>
#include <vector>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::vector;
using std::make_pair;

class Path
{
    vector< pair<char, int> > _path;
public:
    Path(int size)
        : _path(size)
    { }

    void setStep(int i, const pair<char, int>& where)
    {
        _path[i] = where;
    }

    int size() const
    {
        return _path.size();
    }

    pair<char, int> getStep(int i) const
    {
        return _path[i];
    }
};

class OldMap
{
    int _width;
    int _height;
    vector< vector<char> >   _map;
    vector< char >           _sights;
    vector< pair<int, int> > _s_pos;
public:
    OldMap(int m, int n)
        :   _width(n), _height(m), _map(m)
    {
        for (int i = 0; i < m; ++i)
            _map[i].resize(n);

    }

    void setMap(int i, int j, char p)
    {
        _map[i][j] = p;

        if (isalpha(p))
        {
            _sights.push_back(p);
            _s_pos.push_back(make_pair(i, j));
        }
    }

    vector<char> possible_good(const Path& path)
    {
        vector<char> res;

        for (size_t i = 0; i < _sights.size(); ++i)
        {
            int x = _s_pos[i].first;
            int y = _s_pos[i].second;

            int step;
            for (step = 0; step < path.size(); ++step)
            {
                pair<char, int> ss = path.getStep(step);

                if (ss.first == 'N')
                {
                    if (x - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[--x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'S')
                {
                    if (x + ss.second >= _height)
                        break;

                    int z;
                    for (z = 0;  z < ss.second; ++z)
                    {
                        if (_map[++x][y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else if (ss.first == 'E')
                {
                    if (y + ss.second >= _width)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][++y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
                else  // ss.first == 'W'
                {
                    if (y - ss.second < 0)
                        break;

                    int z;
                    for (z = 0; z < ss.second; ++z)
                    {
                        if (_map[x][--y] == '#')
                            break;
                    }
                    if (z < ss.second)
                        break;
                }
            }

            if (step == path.size())
                res.push_back(_sights[i]);
        }

        return res;
    }
};

int main()
{
    int n;
    int m;
    char c;

    cin >> m >> n;

    OldMap oldmap(m, n);

    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> c;

            oldmap.setMap(i, j, c);
        }

        cin >> c;
    }

    int k = 0;
    cin >> k;

    Path path(k);

    for (int i = 0; i < k; ++i)
    {
        do
        {
            cin >> c;
        } while (!isalpha(c));

        int length;
        cin >> length;

        path.setStep(i, make_pair<char, int>(c, length));
    }

    vector<char> good = oldmap.possible_good(path);

    if (good.size())
    {
        int s = good.size();

        for (int i = 0; i < s; ++i)
            cout << good[i];

        cout << endl;
    }
    else
        cout << "no solution" << endl;

    return 0;
}


#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>

using std::sort;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::vector;
using std::make_pair;

class Path
{
    vector< pair<char, int> > _path;
public:
    Path(int size)
        : _path(size)
    { }

    void setStep(int i, const pair<char, int>& where)
    {
        _path[i] = where;
    }

    int size() const
    {
        return _path.size();
    }

    pair<char, int> getStep(int i) const
    {
        return _path[i];
    }
};

class OldMap
{
    int _width;
    int _height;
    vector< vector<char> >   _map;
    vector< vector<int> >    _matrix;
    vector< char >           _sights;
    vector< pair<int, int> > _s_pos;
public:
    OldMap(int m, int n)
        :   _width(n), _height(m), _map(m), _matrix(m)
    {
        for (int i = 0; i < m; ++i)
        {
            _map[i].resize(n);
            _matrix[i].resize(n);
        }
    }

    void setMap(int i, int j, char p)
    {
        _map[i][j] = p;

        if (isalpha(p))
        {
            _sights.push_back(p);
            _s_pos.push_back(make_pair(i, j));
        }
    }

    void precalc()
    {
        for (int i = 0; i < _height; ++i)
            _matrix[i][0] = 1;

        for (int i = 0; i < _width; ++i)
            _matrix[0][i] = 1;

        for (int i = 1; i < _height; ++i)
        for (int j = 1; j < _width;  ++j)
        {
            _matrix[i][j] = _matrix[i - 1][j] + _matrix[i][j - 1] - _matrix[i - 1][j - 1] + (_map[i][j] == '#');
        }
    }

    vector<char> possible_good(const Path& path)
    {
        vector<char> res;

        for (size_t i = 0; i < _sights.size(); ++i)
        {
            int x = _s_pos[i].first;
            int y = _s_pos[i].second;

            int step;
            for (step = 0; step < path.size(); ++step)
            {
                pair<char, int> ss = path.getStep(step);

                if (ss.first == 'N')
                {
                    if ((x - ss.second < 1) || (_matrix[x][y] - _matrix[x][y - 1] - _matrix[x - ss.second - 1][y] + _matrix[x - ss.second - 1][y - 1]))
                        break;

                    x -= ss.second;
                }
                else if (ss.first == 'S')
                {
                    if ((x + ss.second >= _height - 1) || (_matrix[x + ss.second][y] - _matrix[x + ss.second][y - 1] - _matrix[x - 1][y] + _matrix[x - 1][y - 1]))
                        break;

                    x += ss.second;
                }
                else if (ss.first == 'E')
                {
                    if ((y + ss.second >= _width - 1) || (_matrix[x][y + ss.second] - _matrix[x][y - 1] - _matrix[x - 1][y + ss.second] + _matrix[x - 1][y - 1]))
                        break;

                    y += ss.second;
                }
                else  // ss.first == 'W'
                {
                    if ((y - ss.second < 1) || (_matrix[x][y] - _matrix[x][y - ss.second - 1] - _matrix[x - 1][y] + _matrix[x - 1][y - ss.second - 1]))
                        break;

                    y -= ss.second;
                }
            }

            if (step == path.size())
                res.push_back(_sights[i]);
        }

        return res;
    }
};

int main()
{
    int n;
    int m;
    char c;

    cin >> m >> n;

    OldMap oldmap(m, n);

    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> c;
            //cerr << "read " << c << endl;

            oldmap.setMap(i, j, c);
        }

        //cerr << "last c " << c << endl;
    }

    int k = 0;
    cin >> k;

    Path path(k);

    for (int i = 0; i < k; ++i)
    {
        do
        {
            cin >> c;
        } while (!isalpha(c));

        int length;
        cin >> length;

        path.setStep(i, make_pair<char, int>(c, length));
    }

    oldmap.precalc();

    vector<char> good = oldmap.possible_good(path);

    if (good.size())
    {
        sort(good.begin(), good.end());

        int s = good.size();

        for (int i = 0; i < s; ++i)
            cout << good[i];

        cout << endl;
    }
    else
        cout << "no solution" << endl;

    return 0;
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m;
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( x - num <= 0 ) return true;
		for ( ; num; num-- ) {
			x--;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else if ( dir == 2 ) {
		if( x + num >= n ) return true;
		for ( ; num ; num--) {
			x++;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else if ( dir == 3 ) {
		if ( y + num >= m ) return true;
		for ( ; num ; num-- ) {
			y++;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else {
		if ( y - num <= 0 ) return true;
		for ( ; num; num--) {
			y--;
			if ( a[x][y] == '#' ) return true;
		}
	}
	return false;
}

int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		queue < pair < int , int > > q;
		q.push(mp(x,y));
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m,sum[1111][1111];
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( x - num - 1 <= 0 ) return true;
		if ( sum[x][y] - sum[x-num - 1][y] - sum[x][y-1] + sum[x-num-1][y-1] != 0) { x = x - num; return true; }
		x -=num;
	}
	else if ( dir == 2 ) {
		if ( x + num > n ) return true;
		if ( sum[x+num][y] - sum[x-1][y] - sum[x+num][y-1] + sum[x-1][y-1] != 0 ) { x = x + num; return true; }
		x += num;
	}
	else if ( dir == 3 ) {
		if ( y + num > m ) return true;
		if ( sum[x][y+num] - sum[x-1][y+num] - sum[x][y-1] + sum[x-1][y-1] != 0 ) { y = y + num; return true;  }
		y += num;
	}
	else if (dir == 4 ) {
		if ( y - num  - 1 <= 0 ) return true;
		if (sum[x][y] - sum[x-1][y] - sum[x][y-num-1] + sum[x-1][y-num-1] != 0 ) { y = y - num; return true; }
	        y -= num;
	}

	return false;
}
int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
			sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + ((a[i][j] == '#') ? 1 : 0 );
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			//cout << x << " " << y << endl;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m,sum[1111][1111];
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( x == num ) return true;
		if ( sum[x][y] - sum[x-num - 1][y] - sum[x][y-1] + sum[x-num-1][y-1] != 0) { x = x - num; return true; }
		x -=num;
	}
	else if ( dir == 2 ) {
		if ( x + num > n ) return true;
		if ( sum[x+num][y] - sum[x-1][y] - sum[x+num][y-1] + sum[x-1][y-1] != 0 ) { x = x + num; return true; }
		x += num;
	}
	else if ( dir == 3 ) {
		if ( y + num > m ) return true;
		if ( sum[x][y+num] - sum[x-1][y+num] - sum[x][y-1] + sum[x-1][y-1] != 0 ) { y = y + num; return true;  }
		y += num;
	}
	else if (dir == 4 ) {
		if ( y == num ) return true;
		if (sum[x][y] - sum[x-1][y] - sum[x][y-num-1] + sum[x-1][y-num-1] != 0 ) { y = y - num; return true; }
	        y -= num;
	}

	return false;
}
int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
			sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + ((a[i][j] == '#') ? 1 : 0 );
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			//cout << x << " " << y << endl;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m,sum[1111][1111];
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( x == num ) return true;
		if ( sum[x][y] - sum[x-num - 1][y] - sum[x][y-1] + sum[x-num-1][y-1] != 0) { x = x - num; return true; }
		x -=num;
	}
	else if ( dir == 2 ) {
		if ( x + num >= n ) return true;
		if ( sum[x+num][y] - sum[x-1][y] - sum[x+num][y-1] + sum[x-1][y-1] != 0 ) { x = x + num; return true; }
		x += num;
	}
	else if ( dir == 3 ) {
		if ( y + num >= m ) return true;
		if ( sum[x][y+num] - sum[x-1][y+num] - sum[x][y-1] + sum[x-1][y-1] != 0 ) { y = y + num; return true;  }
		y += num;
	}
	else if (dir == 4 ) {
		if ( y == num ) return true;
		if (sum[x][y] - sum[x-1][y] - sum[x][y-num-1] + sum[x-1][y-num-1] != 0 ) { y = y - num; return true; }
	        y -= num;
	}

	return false;
}
int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
			sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + ((a[i][j] == '#') ? 1 : 0 );
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			//cout << x << " " << y << endl;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m,sum[1111][1111];
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( sum[x][y] - sum[x-num - 1][y] - sum[x][y-1] + sum[x-num-1][y-1] != 0) { x = x - num; return true; }
		x -=num;
	}
	else if ( dir == 2 ) {
		if ( sum[x+num][y] - sum[x-1][y] - sum[x+num][y-1] + sum[x-1][y-1] != 0 ) { x = x + num; return true; }
		x += num;
	}
	else if ( dir == 3 ) {
		if ( sum[x][y+num] - sum[x-1][y+num] - sum[x][y-1] + sum[x-1][y-1] != 0 ) { y = y + num; return true;  }
		y += num;
	}
	else if (dir == 4 ) {
		if (sum[x][y] - sum[x-1][y] - sum[x][y-num-1] + sum[x-1][y-num-1] != 0 ) { y = y - num; return true; }
	        y -= num;
	}

	return false;
}
int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
			sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + ((a[i][j] == '#') ? 1 : 0 );
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			//cout << x << " " << y << endl;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m;
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		for ( ; num; num-- ) {
			x--;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else if ( dir == 2 ) {
		for ( ; num ; num--) {
			x++;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else if ( dir == 3 ) {
		for ( ; num ; num-- ) {
			y++;
			if ( a[x][y] == '#' ) return true;
		}
	}
	else {
		for ( ; num; num--) {
			y--;
			if ( a[x][y] == '#' ) return true;
		}
	}
	return false;
}

int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		queue < pair < int , int > > q;
		q.push(mp(x,y));
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <bits/stdc++.h>

#define f first
#define s second
#define mp make_pair
#define pb push_back

using namespace std;

char a[1111][1111],to[111111];
int num[111111],k,n,m,sum[1111][1111];
vector < pair < int , int > > v;
vector < char > ans;

bool fail(int &x,int &y,int dir, int num)
{
	if ( dir == 1 ) {
		if ( x == num ) return true;
		if ( sum[x][y] - sum[x-num - 1][y] - sum[x][y-1] + sum[x-num-1][y-1] != 0) { x = x - num; return true; }
		x -=num;
	}
	else if ( dir == 2 ) {
		if ( x + num >= n ) return true;
		if ( sum[x+num][y] - sum[x-1][y] - sum[x+num][y-1] + sum[x-1][y-1] != 0 ) { x = x + num; return true; }
		x += num;
	}
	else if ( dir == 3 ) {
		if ( y + num >= m ) return true;
		if ( sum[x][y+num] - sum[x-1][y+num] - sum[x][y-1] + sum[x-1][y-1] != 0 ) { y = y + num; return true;  }
		y += num;
	}
	else if (dir == 4 ) {
		if ( y - num <= m ) return true;
		if (sum[x][y] - sum[x-1][y] - sum[x][y-num-1] + sum[x-1][y-num-1] != 0 ) { y = y - num; return true; }
	        y -= num;
	}

	return false;
}
int main()
{
	cin >> n >> m;
	for ( int i = 1; i <= n; i++ )
		for ( int j = 1; j <= m; j++ ) {
			cin >> a[i][j];
			if ( isupper(a[i][j]) ) v.pb(mp(i,j));
			sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + ((a[i][j] == '#') ? 1 : 0 );
		}

	cin >> k;
	for ( int i = 1; i <= k; i++ )
		cin >> to[i] >> num[i];

	for ( int i = 0; i < v.size(); i++ ) {
		int x = v[i].f,y = v[i].s;
		int no = 0,dir;
		for ( int j = 1; j <= k; j++ ) {
			if ( to[j] == 'N' ) dir = 1;
			else if ( to[j] == 'S' ) dir = 2;
			else if ( to[j] == 'E' ) dir = 3;
			else dir = 4;
			//cout << x << " " << y << endl;
			if ( fail(x,y,dir,num[j]) ) { no = 1; break; }
		}
		if (!no) ans.pb(a[v[i].f][v[i].s]);
	}
	if ( ans.empty() ) { puts("no solution"); return 0; }
	sort(ans.begin(),ans.end());
	for ( int i = 0; i < ans.size(); i++ )
		cout << ans[i];
}


#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>

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

using namespace std;

#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define fornd(i, n) for (int i = n - 1; i >= 0; --i)

typedef vector <int> vi;
typedef pair <int, int> pii;
typedef long long ll;
typedef long double ld;

const int inf = 1 << 30;
const ll linf = 1LL << 60;
const int _y[4] = {0, 1, 0, -1};
const int _x[4] = {-1, 0, 1, 0};

const int shft = 1000;

const int maxn = 2005;

int n, m;

char A[maxn][maxn];
bool B[maxn][maxn];

vector <pair <int, int> > bp;
vector <char> ans;

inline void solve(int x, int y) {
  int sx, sy;
  for (int i = 0; i < bp.size(); ++i) {
    sx = x + bp[i].first;
    sy = y + bp[i].second;

    //cerr << x << " " << y << " | " << sx << " " << sy << " " << A[sx][sy] << endl;

    if (sx < 0 || sy < 0 || sx >= n || sy >= m || A[sx][sy] == '#')
      return;
  }

  ans.pb(A[x][y]);
}

void fail() {
  printf("no solution");
  exit(0);
}

int main() {
//  freopen(".in", "r", stdin);

  scanf("%d%d\n", &n, &m);

  for (int i = 0; i < n; ++i) {
    scanf("%s\n", A[i]);
  }

  int k;
  cin >> k;

  bp.reserve(maxn * maxn);
  int x = 0, y = 0;
  B[x + shft][y + shft] = 1;
  bp.pb(mp(x, y));

  for (int i = 0; i < k; ++i) {
    char c;
    int len;
    scanf("%c %d\n", &c, &len);

    int op;
    switch (c) {
      case 'N':
        op = 0;
        break;
      case 'W':
        op = 1;
        break;
      case 'S':
        op = 2;
        break;
      case 'E':
        op = 3;
    }

    for (int i = 0; i < len; ++i) {
      x = x + _x[op];
      y = y + _y[op];

      if (x < -shft || y < -shft || x > shft || y > shft)
        fail();

      if (!B[x + shft][y + shft]) {
        B[x + shft][y + shft] = 1;
        bp.pb(mp(x, y));
      }
    }
  }

  ans.reserve(30);

  forn(i, n)
    forn(j, m)
      if (A[i][j] != '#' && A[i][j] != '.')
        solve(i, j);

  sort(all(ans));

  forn(i, sz(ans))
    printf("%c", ans[i]);

  if (!sz(ans))
    fail();

  return 0;
}


#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>

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

using namespace std;

#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define fornd(i, n) for (int i = n - 1; i >= 0; --i)

typedef vector <int> vi;
typedef pair <int, int> pii;
typedef long long ll;
typedef long double ld;

const int inf = 1 << 30;
const ll linf = 1LL << 60;
const int _y[4] = {0, 1, 0, -1};
const int _x[4] = {-1, 0, 1, 0};

const int shft = 1000;

const int maxn = 2005;

int n, m;

char A[maxn][maxn];
bool B[maxn][maxn];

vector <pair <int, int> > bp;
vector <char> ans;

inline void solve(int x, int y) {
  int sx, sy;
  for (int i = 0; i < bp.size(); ++i) {
    sx = x + bp[i].first;
    sy = y + bp[i].second;

    //cerr << x << " " << y << " | " << sx << " " << sy << " " << A[sx][sy] << endl;

    if (sx < 0 || sy < 0 || sx >= n || sy >= m || A[sx][sy] == '#')
      return;
  }

  ans.pb(A[x][y]);
}

void fail() {
  printf("no solution");
  exit(0);
}

int main() {
  //freopen("D.in", "r", stdin);

  scanf("%d%d\n", &n, &m);

  for (int i = 0; i < n; ++i) {
    scanf("%s\n", A[i]);
  }

  int k;
  scanf("%d\n", &k);
  bp.reserve(maxn * maxn);
  int x = 0, y = 0;
  B[x + shft][y + shft] = 1;
  bp.pb(mp(x, y));

  for (int i = 0; i < k; ++i) {
    char c;
    int len;
    scanf("%c %d\n", &c, &len);

    int op;
    switch (c) {
      case 'N':
        op = 0;
        break;
      case 'E':
        op = 1;
        break;
      case 'S':
        op = 2;
        break;
      case 'W':
        op = 3;
    }

    //cerr << c << " " << op << " " << len << endl;
    for (int i = 0; i < len; ++i) {
      x = x + _x[op];
      y = y + _y[op];

      if (x < -shft || y < -shft || x > shft || y > shft)
        fail();

      if (!B[x + shft][y + shft]) {
        B[x + shft][y + shft] = 1;
        bp.pb(mp(x, y));
      }
    }
  }

  ans.reserve(30);

  forn(i, n)
    forn(j, m)
      if (A[i][j] != '#' && A[i][j] != '.')
        solve(i, j);

  sort(all(ans));

  forn(i, sz(ans))
    printf("%c", ans[i]);

  if (!sz(ans))
    fail();

  return 0;
}


#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>

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

using namespace std;

#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define fornd(i, n) for (int i = n - 1; i >= 0; --i)

typedef vector <int> vi;
typedef pair <int, int> pii;
typedef long long ll;
typedef long double ld;

const int inf = 1 << 30;
const ll linf = 1LL << 60;
const int _y[4] = {0, 1, 0, -1};
const int _x[4] = {-1, 0, 1, 0};

const int shft = 1000;

const int maxn = 2005;

int n, m;

char A[maxn][maxn];
bool B[maxn][maxn];

vector <pair <int, int> > bp;
vector <char> ans;

inline void solve(int x, int y) {
  int sx, sy;
  for (int i = 0; i < bp.size(); ++i) {
    sx = x + bp[i].first;
    sy = y + bp[i].second;

    //cerr << x << " " << y << " | " << sx << " " << sy << " " << A[sx][sy] << endl;

    if (sx < 0 || sy < 0 || sx >= n || sy >= m || A[sx][sy] == '#')
      return;
  }

  ans.pb(A[x][y]);
}

void fail() {
  printf("no solution");
  exit(0);
}

int main() {
//  freopen(".in", "r", stdin);

  scanf("%d%d\n", &n, &m);

  for (int i = 0; i < n; ++i) {
    scanf("%s\n", A[i]);
  }

  int k;
  cin >> k;

  bp.reserve(maxn * maxn);
  int x = 0, y = 0;
  B[x + shft][y + shft] = 1;
  bp.pb(mp(x, y));

  for (int i = 0; i < k; ++i) {
    char c;
    int len;
    scanf("%c %d\n", &c, &len);

    int op;
    switch (c) {
      case 'N':
        op = 0;
        break;
      case 'E':
        op = 1;
        break;
      case 'S':
        op = 2;
        break;
      case 'W':
        op = 3;
    }

    for (int i = 0; i < len; ++i) {
      x = x + _x[op];
      y = y + _y[op];

      if (x < -shft || y < -shft || x > shft || y > shft)
        fail();

      if (!B[x + shft][y + shft]) {
        B[x + shft][y + shft] = 1;
        bp.pb(mp(x, y));
      }
    }
  }

  ans.reserve(30);

  forn(i, n)
    forn(j, m)
      if (A[i][j] != '#' && A[i][j] != '.')
        solve(i, j);

  sort(all(ans));

  forn(i, sz(ans))
    printf("%c", ans[i]);

  if (!sz(ans))
    fail();

  return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <vector>
#include <map>
using namespace std;
#define N 1005
vector<char>ans ;
struct node{
    int x, y;
    char c;
    void put(){printf("(%d,%d) : %c\n", x, y, c);}
}a[30];
int step[4][2] = {-1,0, 1,0, 0,-1, 0,1};
int work[100005][2];
char s[N];
int mp[N][N], n, m, k, top, h[N][N], l[N][N] ;
bool okh(int H, int x, int y)
{
    return h[H][y]-h[H][x-1] == 0;
}
bool okl(int L, int x, int y)
{
    return l[L][y]-l[L][x-1] == 0;
}
bool ok(int x, int y, int i, int j)
{
    if(x>i)swap(x,i); if(y>j)swap(y,j);
    if(x==i)
        return okh(x, y, j);
    else
        return okl(y, x, i);
}
bool inmap(int x, int y)
{
    return 1<=x&&x<=n&&1<=y&&y<=m;
}
bool judge(int x, int y)
{
    for(int i = 0; i < k; i++)
    {
        int ux = step[work[i][0]][0] * work[i][1] + x, uy = step[work[i][0]][1] *work[i][1] + y;
        if(!inmap(ux,uy))return false;  // 判断出界
        if(!ok(x, y, ux, uy))return false;
        x = ux; y = uy;
    }
    return true;
}
void debug(){for(int i = 0; i < top; i++)a[i].put();}
void solve()
{
 //   debug();
    ans.clear();
    for(int i = 0; i < top; i++)
        if(judge(a[i].x, a[i].y))
            ans.push_back(a[i].c);
    if(ans.size()==0)
    {
        puts("no solution");
        return ;
    }
    sort(ans.begin(), ans.end());
    for(int i = 0; i < ans.size(); i++)printf("%c",ans[i]);
    puts("");
}
void input()
{
    top = 0;
    memset(mp, 0, sizeof mp);
    memset(h, 0, sizeof h);
    memset(l, 0, sizeof l);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", s+1);
        for(int j = 1; j <= m; j++)
        {
            if(s[j]=='#')
            {
                mp[i][j] = 1;
                h[i][j] = 1;
                l[j][i] = 1;
            }
            else if('A'<=s[j] && s[j]<='Z'){
                    a[top].x = i; a[top].y = j; a[top].c = s[j];
                    top++;
            }
        }
    }
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            h[i][j] += h[i][j-1];
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            l[i][j] += l[i][j-1];
    scanf("%d",&k);
    for(int i = 0; i < k; i++)
    {
        scanf("%s %d", s, &work[i][1]);
        if(s[0] == 'N') work[i][0] = 0;
        else if(s[0]=='S') work[i][0] = 1;
        else if(s[0]=='W') work[i][0] = 2;
        else work[i][0] = 3;
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        input();
        solve();
    }
    return 0;
}


#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std  ;
#define INT __int64
const int INF = 99999999 ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int MY = 100000 + 5 ;
const int MX = 1000 + 5 ;
int n ,m ,sg ,Q ;
char s[MX] ;
int Lx[MX][MX] ,Ly[MX][MX] ,mp[MX][MX] ;
int dx[4] = {-1 ,1 ,0 ,0} ,dy[4] = {0 ,0 ,-1 ,1} ;
struct Sigt
{
    char ch ;
    int x ,y ;
}SG[30] ;
struct MOVE
{
    int dir ,step ;
}Move[100005] ;
void input()
{
    char ch ;
    int x ,y ;
    sg = 0 ;
    memset(mp ,0 ,sizeof(mp)) ;
    memset(Lx ,0 ,sizeof(Lx)) ;
    memset(Ly ,0 ,sizeof(Ly)) ;
    for(int i = 1 ;i <= n ; ++i)
    {
         cin>>s ;
         for(int j = 1 ;j <= m ; ++j)
          if(s[j] >= 'A' && s[j] <= 'Z')
          {
              SG[sg].x = i ;
              SG[sg].y = j ;
              SG[sg++].ch = s[j] ;
          }
          else if(s[j] == '#')
          {
              mp[i][j] = 1 ;
              Lx[i][j] = 1 ;
              Ly[j][i] = 1 ;
          }
    }
    cin>>Q ;
    for(int i = 0 ;i < Q ; ++i)
    {
        cin>>ch>>x ;
        if(ch == 'N')
              y = 0 ;
        else if(ch == 'S')
              y = 1 ;
        else if(ch == 'W')
              y = 2 ;
        else   y = 3 ;
        Move[i].dir = y ;
        Move[i].step = x ;
    }
    for(int i = 1 ;i <= n ; ++i)
      for(int j = 1 ;j <= m ; ++j)
         Lx[i][j] += Lx[i][j-1] ;
    for(int j = 1 ;j <= m ; ++j)
      for(int i = 1 ;i <= n ; ++i)
         Ly[j][i] += Ly[j][i-1] ;
}
bool judge(int x ,int y)
{
    int ax ,ay ,sx ,sy ,bx ,by ,dir ,step ;
    for(int i = 0 ;i < Q ; ++i)
    {
        dir = Move[i].dir ;
        step = Move[i].step ;
        sx = x + dx[dir]*step ;
        sy = y + dy[dir]*step ;
        if(sx <= 0 || sx > n || sy <= 0 || sy > m || mp[sx][sy])   // 判断出界
                return false ;
        ax = x ; ay = y ;
        bx = sx ; by = sy ;
        if(ax > bx)
                swap(ax ,bx) ;
        if(ay > by)
                swap(ay ,by) ;
        if(ax == bx) // x 相等
        {
            if(Lx[ax][by] - Lx[ax][ay-1])
                   return false ;
            if(y != ay)  y = ay ;
            else   y = by ;
        }
        else  // y 相等
        {
            if(Ly[ay][bx] - Ly[ay][ax-1])
                   return  false ;
            if(x != ax)   x = ax ;
            else   x = bx ;
        }
    }
    return true ;
}
void solve()
{
    int nx = 0 ;
    for(int i = 0 ;i < sg ; ++i)
      if(judge(SG[i].x ,SG[i].y))
          s[nx++] = SG[i].ch ;
    if(!nx)
           cout<<"no solution"<<endl ;
    else
    {
        s[nx] = '\0' ;
        sort(s ,s+nx) ;
        cout<<s<<endl ;
    }
}
int main()
{
    while(~scanf("%d%d" ,&n ,&m))
    {
       input() ;
       solve() ;
    }
    return 0 ;
}


#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std  ;
#define INT __int64
const int INF = 99999999 ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int MY = 100000 + 5 ;
const int MX = 1000 + 5 ;
int n ,m ,num ,Q ,Gnum ;
char s[MX][MX] ,s1[50] ;
int dx[4] = {-1 ,1 ,0 ,0} ,dy[4] = {0 ,0 ,-1 ,1} ; // N ,S ,W ,E
vector<int>Gx[MX] ,Gy[MX] ;
struct node // 存景点
{
    char ch ;
    int x ,y ;
}T[50] ;
struct move // 各条指令
{
    int dir ,step ;
}Move[MY] ;
void input()
{
    int x ,y ;
    num = 0 ; // 记录景点个数
    Gnum = 0 ;// 记录 # 的个数
    for(int i = 0 ;i < n ; ++i)
    {
        scanf("%s" ,s[i]) ;
        for(int j = 0 ;j < m ; ++j)
          if(s[i][j] >= 'A' && s[i][j] <= 'Z') // 是景点
          {
             T[num].x = i ;
             T[num].y = j ;
             T[num++].ch = s[i][j] ;
          }
          else if(s[i][j] == '#') // 是墙
          {
              Gx[i].push_back(j) ;
              Gy[j].push_back(i) ;
          }
    }
    scanf("%d" ,&Q) ;
    char ch ;
    for(int i = 0 ;i < Q ; ++i) // 输入指令
    {
        cin>>ch>>x ;
        if(ch == 'N')
                y = 0 ;
        else if(ch == 'S')
                y = 1 ;
        else if(ch == 'W')
                y = 2 ;
        else    y = 3 ;
        Move[i].dir = y ; // 记录指令
        Move[i].step = x ;
    }
}
bool solve(int x ,int y)
{
    int sx ,sy ,dir ,step ,mt ;
    for(int i = 0 ;i < Q ; ++i) // 一次执行 Q 条指令
    {
        dir = Move[i].dir ;
        step = Move[i].step ;
        if(!dir) // N    y 不变 上
        {
            sx = x + dx[dir]*step ;
            mt = Gy[y].size() ;
            if(sx < 0 || sx >= n)  return false ; // 出界
            for(int j = 0 ;j < mt ; ++j)
              if(Gy[y][j] >= sx && Gy[y][j] < x)
                   return false ;
            x = sx ;
        }
        else if(dir == 1) // S 下  y 不变
        {
            sx = x + dx[dir]*step ;
            mt = Gy[y].size() ;
            if(sx < 0 || sx >= n)  return false ; // 出界
            for(int j = 0 ;j < mt ; ++j)
              if(Gy[y][j] > x && Gy[y][j] <= sx)
                   return false ;
            x = sx ;
        }
        else if(dir == 2) // W 左  x 不变
        {
            sy = y + dy[dir]*step ;
            mt = Gx[x].size() ;
            if(sy < 0 || sy >= m)  return false ;
            for(int j= 0 ;j < mt ; ++j)
              if(Gx[x][j] < y && Gx[x][j] >= sy)
                   return false ;
            y = sy ;
        }
        else  // E 右  x 不变
        {
            sy = y + dy[dir]*step ;
            mt = Gx[x].size() ;
            if(sy < 0 || sy >= m)  return false ;
            for(int j= 0 ;j < mt ; ++j)
              if(Gx[x][j] > y && Gx[x][j] <= sy)
                   return false ;
            y = sy ;
        }
    }
    return true ;
}
int main()
{
    while(~scanf("%d%d" ,&n ,&m))
    {
        input() ;
        int nx = 0 ;
        bool flag = false ;
        for(int i = 0 ;i < num ; ++i)
          if(solve(T[i].x ,T[i].y)) // 判断此起点是否合法
            {
               flag = true ;
               s1[nx++] = T[i].ch ;
            }
        if(flag)
        {
            s1[nx] = '\0' ;
            stable_sort(s1 ,s1+nx) ;
            cout<<s1<<endl ;
        }
        else   cout<<"no solution"<<endl ;
        for(int i = 0 ;i < Gnum ; ++i)
        {
            Gx[i].clear() ;
            Gy[i].clear() ;
        }
    }
    return 0 ;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int c_o[4] = {0, 1, 0, -1};
int r_o[4] = {-1, 0, 1, 0};

struct s
{
    s(int nr, int nc, char nl) : r(nr), c(nc), l(nl){u = true;}
    int r, c;
    char l;
    bool u;
};

bool operator < (const s &lhs, const s&rhs)
{
    return lhs.l < rhs.l;
}

int main(void)
{
    int r, c, n, steps;
    char d;
    map<char, int> dirs;
    dirs['N'] = 0;
    dirs['E'] = 1;
    dirs['S'] = 2;
    dirs['W'] = 3;

    cin >> r >> c;
    vector<string> grid(r);
    vector<s> ss;
    for(int i = 0; i < r; i++)
        cin >> grid[i];
//    for(int i = 0; i < r; i++)
//        cout << grid[i] << '\n';

    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            if(grid[i][j] >= 'A' && grid[i][j] <= 'Z')
                ss.push_back(s(i, j, grid[i][j]));

    sort(ss.begin(), ss.end());
//    for(int i = 0; i < ss.size(); i++)
//        cout << '(' << ss[i].r << ',' << ss[i].c << ") " << ss[i].l << ' ' << ss[i].u << '\n';

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> d >> steps;
        for(int j = 0; j < ss.size(); j++)
        {
            for(int k = 1; k <= steps; k++)
            {
                ss[j].r += r_o[dirs[d]];
                ss[j].c += c_o[dirs[d]];
                if(    ss[j].r < 0 || ss[j].r >= r
                    || ss[j].c < 0 || ss[j].c >= c
                    || (ss[j].r >= 0 && ss[j].r < r && ss[j].c >= 0 && ss[j].c < c && grid[ss[j].r][ss[j].c] == '#'))
                {
                    ss[j].u = false;
//                    cout << i << ' ' << ss[i].r << ' ' << ss[i].c << ' ' << d << ' ' << k << ' ' << ss[j].l << '\n';
                }
            }
        }
    }

    bool left = false;
    for(int i = 0; i < ss.size(); i++)
        if(ss[i].u == true)
        {
            left = true;
            break;
        }

    if(left)
    {
        for(int i = 0; i < ss.size(); i++)
            if(ss[i].u == true)
                cout << ss[i].l;
    }
    else
        cout << "no solution";

    cout << '\n';
    return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int c_o[4] = {0, 1, 0, -1};
int r_o[4] = {-1, 0, 1, 0};

struct s
{
    s(int nr, int nc, char nl) : r(nr), c(nc), l(nl){u = true;}
    int r, c;
    char l;
    bool u;
};

bool operator < (const s &lhs, const s&rhs)
{
    return lhs.l < rhs.l;
}

int main(void)
{
    int r, c, n, steps;
    char d;
    map<char, int> dirs;
    dirs['N'] = 0;
    dirs['E'] = 1;
    dirs['S'] = 2;
    dirs['W'] = 3;

    cin >> r >> c;
    vector<string> grid(r);
    vector<s> ss;
    for(int i = 0; i < r; i++)
        cin >> grid[i];

    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            if(grid[i][j] >= 'A' && grid[i][j] <= 'Z')
                ss.push_back(s(i, j, grid[i][j]));

    sort(ss.begin(), ss.end());

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> d >> steps;
        for(int j = 0; j < ss.size(); j++)
        {
            if(ss[j].u == true)
            for(int k = 1; k <= steps; k++)
            {
                {
                    ss[j].r += r_o[dirs[d]];
                    ss[j].c += c_o[dirs[d]];
                    if(    ss[j].r < 0 || ss[j].r >= r
                        || ss[j].c < 0 || ss[j].c >= c
                        || (ss[j].r >= 0 && ss[j].r < r && ss[j].c >= 0 && ss[j].c < c && grid[ss[j].r][ss[j].c] == '#'))
                    {
                        ss[j].u = false;
                    }
                }
            }
        }
    }

    bool left = false;
    for(int i = 0; i < ss.size(); i++)
        if(ss[i].u == true)
        {
            left = true;
            break;
        }

    if(left)
    {
        for(int i = 0; i < ss.size(); i++)
            if(ss[i].u == true)
                cout << ss[i].l;
    }
    else
        cout << "no solution";

    cout << '\n';
    return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int c_o[4] = {0, 1, 0, -1};
int r_o[4] = {-1, 0, 1, 0};

struct s
{
    s(int nr, int nc, char nl) : r(nr), c(nc), l(nl){u = true;}
    int r, c;
    char l;
    bool u;
};

bool operator < (const s &lhs, const s&rhs)
{
    return lhs.l < rhs.l;
}

int main(void)
{
    int r, c, n, steps;
    char d;
    map<char, int> dirs;
    dirs['N'] = 0;
    dirs['E'] = 1;
    dirs['S'] = 2;
    dirs['W'] = 3;

    cin >> r >> c;
    vector<string> grid(r);
    vector<s> ss;
    for(int i = 0; i < r; i++)
        cin >> grid[i];

    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            if(grid[i][j] >= 'A' && grid[i][j] <= 'Z')
                ss.push_back(s(i, j, grid[i][j]));

    sort(ss.begin(), ss.end());

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> d >> steps;
        for(int j = 0; j < ss.size(); j++)
        {
            if(ss[j].u == true)
            for(int k = 1; k <= steps; k++)
            {
                {
                    ss[j].r += r_o[dirs[d]];
                    ss[j].c += c_o[dirs[d]];
                    if(    ss[j].r < 0 || ss[j].r >= r
                        || ss[j].c < 0 || ss[j].c >= c
                        || grid[ss[j].r][ss[j].c] == '#')
                    {
                        ss[j].u = false;
                        break;
                    }
                }
            }
        }
    }

    bool left = false;
    for(int i = 0; i < ss.size(); i++)
        if(ss[i].u == true)
        {
            left = true;
            break;
        }

    if(left)
    {
        for(int i = 0; i < ss.size(); i++)
            if(ss[i].u == true)
                cout << ss[i].l;
    }
    else
        cout << "no solution";

    cout << '\n';
    return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int c_o[4] = {0, 1, 0, -1};
int r_o[4] = {-1, 0, 1, 0};

struct s
{
    s(int nr, int nc, char nl) : r(nr), c(nc), l(nl){u = true;}
    int r, c;
    char l;
    bool u;
};

bool operator < (const s &lhs, const s&rhs)
{
    return lhs.l < rhs.l;
}

int main(void)
{
    int r, c, n, steps;
    char d;
    map<char, int> dirs;
    dirs['N'] = 0;
    dirs['E'] = 1;
    dirs['S'] = 2;
    dirs['W'] = 3;

    cin >> r >> c;
    vector<string> grid(r);
    vector<s> ss;
    for(int i = 0; i < r; i++)
        cin >> grid[i];

    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            if(grid[i][j] >= 'A' && grid[i][j] <= 'Z')
                ss.push_back(s(i, j, grid[i][j]));

    sort(ss.begin(), ss.end());

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> d >> steps;
        for(int j = 0; j < ss.size(); j++)
        {
            if(ss[j].u == true)
            for(int k = 1; k <= steps; k++)
            {
                {
                    ss[j].r += r_o[dirs[d]];
                    ss[j].c += c_o[dirs[d]];
                    if(    ss[j].r < 0 || ss[j].r >= r
                        || ss[j].c < 0 || ss[j].c >= c
                        || grid[ss[j].r][ss[j].c] == '#')
                    {
                        ss[j].u = false;
                    }
                }
            }
        }
    }

    bool left = false;
    for(int i = 0; i < ss.size(); i++)
        if(ss[i].u == true)
        {
            left = true;
            break;
        }

    if(left)
    {
        for(int i = 0; i < ss.size(); i++)
            if(ss[i].u == true)
                cout << ss[i].l;
    }
    else
        cout << "no solution";

    cout << '\n';
    return 0;
}


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;

int c_o[4] = {0, 1, 0, -1};
int r_o[4] = {-1, 0, 1, 0};

struct s
{
    s(int nr, int nc, char nl) : r(nr), c(nc), l(nl){u = true;}
    int r, c;
    char l;
    bool u;
};

bool operator < (const s &lhs, const s&rhs)
{
    return lhs.l < rhs.l;
}

int main(void)
{
    int r, c, n, steps;
    char d;
    map<char, int> dirs;
    dirs['N'] = 0;
    dirs['E'] = 1;
    dirs['S'] = 2;
    dirs['W'] = 3;

    cin >> r >> c;
    vector<string> grid(r);
    vector<s> ss;
    vector< vector< vector<int> > > left(r, vector< vector<int> >(c, vector<int>(4,0)));
    for(int i = 0; i < r; i++)
        cin >> grid[i];

    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            if(grid[i][j] >= 'A' && grid[i][j] <= 'Z')
                ss.push_back(s(i, j, grid[i][j]));

    //figure out how far you can go in each direction
    //N
    for(int j = 0; j < c; j++)
        for(int i = 1; i < r; i++)
            if(grid[i-1][j] != '#')
                left[i][j][dirs['N']] = left[i-1][j][dirs['N']] + 1;
    //S
    for(int j = 0; j < c; j++)
        for(int i = r-2; i >= 0; i--)
            if(grid[i+1][j] != '#')
                left[i][j][dirs['S']] = left[i+1][j][dirs['S']] + 1;
    //W
    for(int i = 0; i < r; i++)
        for(int j = 1; j < c; j++)
            if(grid[i][j-1] != '#')
                left[i][j][dirs['W']] = left[i][j-1][dirs['W']] + 1;
    //E
    for(int i = 0; i < r; i++)
        for(int j = c-2; j >=0 ; j--)
            if(grid[i][j+1] != '#')
                left[i][j][dirs['E']] = left[i][j+1][dirs['E']] + 1;

    sort(ss.begin(), ss.end());

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> d >> steps;
        for(int j = 0; j < ss.size(); j++)
        {
            if(ss[j].u == true)
            {
                if(steps <= left[ss[j].r][ss[j].c][dirs[d]])
                {
                    ss[j].r += r_o[dirs[d]] * steps;
                    ss[j].c += c_o[dirs[d]] * steps;
                }
                else
                    ss[j].u = false;
            }
        }
    }

    bool good = false;
    for(int i = 0; i < ss.size(); i++)
        if(ss[i].u == true)
        {
            good = true;
            break;
        }

    if(good)
    {
        for(int i = 0; i < ss.size(); i++)
            if(ss[i].u == true)
                cout << ss[i].l;
    }
    else
        cout << "no solution";

    cout << '\n';
    return 0;
}