#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
 
 
#define MAX 25
typedef complex<double> COMPLEX;
typedef vector<COMPLEX> V;
typedef vector<V> MATRIX;
 
 
ll size_A,size_B,K,L;
char map_A[505][505],map_B[505][505];
char buf[200005];
 
 
struct Info{
    Info(int arg_left,int arg_right){
        left = arg_left;
        right = arg_right;
    }
    int left,right;
};
 
int POW[MAX];
int LR_rev[1000005];
vector<Info> info;
vector<COMPLEX> MULT[MAX];
 
 
void calc_swap_pair(int N,int num_pow){
 
    LR_rev[0] = 0;
 
    for(int i = 1; i < N; i++){
 
        if(i%2 == 1){
 
            LR_rev[i] = LR_rev[i-1]+POW[num_pow-1]; //1を足す代わりにPOW[num_pow-1]を足す
 
        }else{
 
            LR_rev[i] = LR_rev[i/2]/2; //半分のインデックスの値に、2を掛ける代わりに2で割る
        }
 
        if(i < LR_rev[i]){
            info.push_back(Info(i,LR_rev[i]));
        }
    }
}
 
void calc_COMPLEX(int N){
 
    for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){
 
        MULT[num_pow].resize(LEN/2);
 
        MULT[num_pow][0] = COMPLEX(cos(0),sin(0));
 
        COMPLEX mult = COMPLEX(cos((2*M_PI)/LEN),sin((2*M_PI)/LEN));
 
        for(int i = 1; i < LEN/2; i++){
 
            if(i%2 == 1){
                MULT[num_pow][i] = MULT[num_pow][i-1]*mult;
            }else{
                MULT[num_pow][i] = MULT[num_pow-1][i/2];
            }
        }
    }
}
 
//離散フーリエ変換
vector<COMPLEX> DFT(vector<COMPLEX> A) {
 
    int N = A.size();
 
    /*偶数項を左に、奇数項を右に仕分けるルールで要素数1まで仕分けした場合の、
     * 最終結果を先に作っておく(ビットが左右反転したものがその位置に来る)*/
    for(int i = 0; i < info.size(); i++){
 
        swap(A[info[i].left],A[info[i].right]);
    }
 
    COMPLEX a,add;
 
    for(int LEN = 2,num_pow = 0; LEN <= N; LEN *= 2,num_pow++){
 
        for(int start = 0; start < N; start += LEN){
            for(int i = 0; i < LEN/2; i++){
                //マージソートの容量で、配列を更新していく
                a = A[start+i];
                add = MULT[num_pow][i]*A[start+LEN/2+i];
 
                A[start+i] = a+add;
                A[start+LEN/2+i] = a-add;
            }
        }
    }
    return A;
}
 
//離散逆フーリエ変換
vector<COMPLEX> inverseDFT(vector<COMPLEX> A){
 
    int N = A.size();
 
    vector<COMPLEX> TMP = DFT(A);
 
    //係数を入れ替える&サイズNで各要素を割る
    vector<COMPLEX> RET(N);
 
    for(int i = 0; i < N; i++){
 
        RET[i] = TMP[(N-i)%N];
        RET[i] = RET[i]/COMPLEX(N,0);
    }
 
    return RET;
}
 
//AとBのサイズは、大きい方に揃えておく
MATRIX convolution2D(MATRIX A,MATRIX B){
 
    int SIZE = A.size();
 
    for(int i = 0; i < MAX; i++){
 
        if(SIZE == POW[i]){
            calc_swap_pair(SIZE,i);
                    break;
        }
    }
    calc_COMPLEX(SIZE);
 
    MATRIX RET(SIZE,V(SIZE));
 
    //行についてのフーリエ変換
    for(int row = 0; row < SIZE; row++){
 
        A[row] = DFT(A[row]);
        B[row] = DFT(B[row]);
    }
 
    //列についてのフーリエ変換を行単位で処理するため、転置
    for(int col = 1; col < SIZE; col++){
        for(int row = 0; row < col; row++){
            swap(A[row][col],A[col][row]);
            swap(B[row][col],B[col][row]);
        }
    }
 
    //列についてのフーリエ変換
    for(int row = 0; row < SIZE; row++){
 
        A[row] = DFT(A[row]);
        B[row] = DFT(B[row]);
    }
 
    //元に戻すため、再転置
    for(int col = 1; col < SIZE; col++){
        for(int row = 0; row < col; row++){
            swap(A[row][col],A[col][row]);
            swap(B[row][col],B[col][row]);
        }
    }
 
    //ここまでの結果を計算
    for(int row = 0; row < SIZE; row++){
        for(int col = 0; col < SIZE; col++){
 
            RET[row][col] = A[row][col]*B[row][col];
        }
    }
 
    //各行をフーリエ逆変換
    for(int row = 0; row < SIZE; row++){
 
        RET[row] = inverseDFT(RET[row]);
    }
 
    //転置
    for(int col = 1; col < SIZE; col++){
        for(int row = 0; row < col; row++){
            swap(RET[row][col],RET[col][row]);
        }
    }
 
    for(int row = 0; row < SIZE; row++){
 
        RET[row] = inverseDFT(RET[row]);
    }
 
    //元に戻すため、再転置
    for(int col = 1; col < SIZE; col++){
        for(int row = 0; row < col; row++){
            swap(RET[row][col],RET[col][row]);
        }
    }
 
    return RET;
}
 
int main(){
 
    POW[0] = 1;
    for(int i = 1; i < MAX; i++){
 
        POW[i] = POW[i-1]*2;
    }
 
    scanf("%lld %lld %lld %lld",&size_A,&size_B,&K,&L);
 
    int SIZE = 1;
    while(SIZE < size_B)SIZE *= 2;
 
    MATRIX A(SIZE,V(SIZE));
    MATRIX B(SIZE,V(SIZE));
 
    for(int row = 0; row < size_A; row++){
 
        scanf("%s",map_A[row]);
        for(int col = 0; col < size_A; col++){
 
            if(map_A[row][col] == 'X'){
                A[row][col] += 1;
            }
        }
    }
 
    scanf("%s",buf);
 
    int row = 0,col = 0;
    for(int i = 0; i < L; i++){
 
        switch(buf[i]){
        case 'U':
            row--;
            break;
        case 'D':
            row++;
            break;
        case 'L':
            col--;
            break;
        case 'R':
            col++;
            break;
        }
        B[row][col] += 1;
    }
 
    MATRIX ret = convolution2D(A,B);
 
    int ans = 0;
 
    for(int row = 0; row < SIZE; row++){
        for(int col = 0; col < SIZE; col++){
 
            if((ll)round(ret[row][col].real()) >= K)ans++;
        }
    }
 
    printf("%d\n",ans);
 
    return 0;
}


Measured memory_bytes: 24268