8 10
cwcwcwcwcw
crcrcrcrcr
cwcwcwcwcw
crcrcrcrcr
cwcwcwcwcw
crcrcrcrcr
cwcwcwcwcw
crcrcrcrcr
12 14
?????r??c?????
?????w????cw?w
??????cr????c?
c?????c??????w
c???????????c?
??c?????cw????
????c?c?c?????
c?????????c???
c?????c?????c?
??????????c??w
?r????c??r????
???w?w??c???c?

0000000000
1010101010
0000000000
1010101010
0000000000
1010101010
0000000000
1010101010

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
5 7
qcezchs
hhedywq
wikywqy
qckrqzt
bqexcxz
3 3
???
yw?
?q?

2 2
cd
ab
3 3
aba
cdc
aba

 */
public class e {
	static void gen() {
		int n = 400, m = 400;
		System.out.println(n + " " +m);
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				System.out.print('a');
			}
			System.out.println();
		}
		System.out.println(n + " " +m);
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				System.out.print('a');
			}
			System.out.println();
		}
		
		
	}
	public static void main(String[] args) throws IOException {
		Object[] arr = new Object[5];
		arr[0] = arr;
		arr[3] = arr;
//		System.out.println(Arrays.deepToString(arr));
//		System.out.println(Arrays.deepToString((Object[]) ((Object[])(((Object[])arr[0])[0]))[0]));
		
//		gen();
		FastScanner in = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int fullRows = in.nextInt(), fullCols = in.nextInt();
		String[] rows = new String[fullRows];
		for (int i = 0; i < fullRows; i++) {
			rows[i] = in.next();
		}
		int patternRows = in.nextInt(), patternCols = in.nextInt();
		String[] prows = new String[patternRows];
		for (int i = 0; i < patternRows; i++) {
			prows[i] = in.next();
		}
		char[][] cs = new char[patternRows+fullRows][patternCols + fullCols];
		for(int i=0;i<cs.length;i++)
			for(int j=0;j<cs[i].length;j++)
			cs[i][j] = rows[i%fullRows].charAt(j % fullCols);
		char[][] ps = new char[patternRows][patternCols];
		for(int i=0;i<ps.length;i++)
			for(int j=0;j<ps[i].length;j++)
				ps[i][j] = prows[i].charAt(j);
		boolean[][] ans = match(cs,ps);
		for (int sr = 0; sr < fullRows; sr++) {
			for (int sc = 0; sc < fullCols; sc++) {
				out.print(ans[sr][sc] ? '1' : '0');
			}
			out.println();
		}
		out.close();
	}

	static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
	static final char wildcard = '?';
	static long[][] ranVs;

	static {
		ranVs = new long[1][alphabet.length()];
		for (int i = 0; i < ranVs.length; i++) {
			for (int j = 0; j < ranVs[i].length; j++) {
				ranVs[i][j] = j;//(long) (Math.random() * 10);
			}
		}
	}

	static boolean[][] match(char[][] source, char[][] pattern) {
		boolean[][] ans = new boolean[source.length][source[0].length];
		for(boolean[]row : ans)
			Arrays.fill(row, true);
		long[][] sourceMat = new long[source.length][source[0].length];
		long[][] patternMat = new long[source.length][source[0].length];
		
		for (int id = 0; id < ranVs.length; id++) {
			for(int i=0;i<source.length;i++) {
				for(int j=0;j<source[i].length;j++) {
					sourceMat[i][j] = ranVs[id][source[i][j]-'a'];
				}
			}
			long hash = 0;
			for(int i=0;i<pattern.length;i++) {
				for(int j=0;j<pattern[i].length;j++) {
					char c = pattern[i][j];
					if (c != wildcard) {
						hash += ranVs[id][c - 'a'] * ranVs[id][c - 'a'];
						patternMat[pattern.length-1-i][pattern[i].length-1-j] = ranVs[id][pattern[i][j]-'a'];
					}
				}
			}
//			System.out.println("hash=" + hash);
			long[][] conv = FFT.multiply2(sourceMat, patternMat);
			for(int i=0;i<source.length;i++) {
				for(int j=0;j<source[i].length;j++) {
					ans[i][j] &= conv[i+pattern.length-1][j+pattern[0].length-1] == hash;
				}
			}
		}
		return ans;
	}
	// SET maxk appropriately!!! ~log(maxn) //%
	static class FFT {
	    static final int maxk = 21, maxn = (1 << maxk) + 1;
	    // Init: wR, wI, rR, rI, aR, aI   to   new double[maxn] !!!
	    //#
	    static double[] wR = new double[maxn],
	            wI = new double[maxn],
	            rR = new double[maxn],
	            rI = new double[maxn],
	            aR  = new double[maxn],
	            aI  = new double[maxn]; //$
	    static int n, k, lastk = -1, dp[] = new int[maxn];

	    static void fft(boolean inv) {
	        if (lastk != k) {
	            lastk = k;  dp[0] = 0;
	            for (int i = 1, g = -1; i < n; i++) {
	                if ((i & (i - 1)) == 0) g++;
	                dp[i] = dp[i ^ (1 << g)] ^ (1 << (k - 1 - g));
	            }
	            wR[1] = 1;
	            wI[1] = 0;
	            for (int t = 0; t < k - 1; t++) {
	                double a = Math.PI / n * (1 << (k - 1 - t));
	                double curR = Math.cos(a), curI = Math.sin(a);
	                int p2 = (1 << t), p3 = p2 * 2;
	                for (int j = p2, k = j * 2; j < p3; j++, k += 2) {
	                    wR[k] = wR[j];
	                    wI[k] = wI[j];
	                    wR[k + 1] = wR[j] * curR - wI[j] * curI;
	                    wI[k + 1] = wR[j] * curI + wI[j] * curR;
	                }
	            }
	        }
	        for (int i = 0; i < n; i++) {
	            int d = dp[i];
	            if (i < d) {
	                double tmp = aR[i];
	                aR[i] = aR[d];
	                aR[d] = tmp;
	                tmp = aI[i];
	                aI[i] = aI[d];
	                aI[d] = tmp;
	            }
	        }
	        if (inv) for (int i = 0; i < n; i++) aI[i] = -aI[i];
	        for (int len = 1; len < n; len <<= 1) {
	            for (int i = 0; i < n; i += len) {
	                int wit = len;
	                for (int it = 0, j = i + len; it < len; it++, i++, j++) {
	                    double tmpR = aR[j] * wR[wit] - aI[j] * wI[wit];
	                    double tmpI = aR[j] * wI[wit] + aI[j] * wR[wit];
	                    wit++;
	                    aR[j] = aR[i] - tmpR;
	                    aI[j] = aI[i] - tmpI;
	                    aR[i] += tmpR;
	                    aI[i] += tmpI;
	                }
	            }
	        }
	    }

	    static long[] multiply(long[] a, long[] b) {
	        int na = a.length, nb = b.length;
	        for (k = 0, n = 1; n < na + nb - 1; n <<= 1, k++) {}
	        for (int i = 0; i < n; ++i) {
	            aR[i] = i < na ? a[i] : 0;
	            aI[i] = i < nb ? b[i] : 0;
	        }
	        fft(false);
	        aR[n] = aR[0];
	        aI[n] = aI[0];
	        double q = -1.0 / n / 4.0;
	        for (int i = 0; i <= n - i; ++i) {
	            double tmpR = aR[i] * aR[i] - aI[i] * aI[i];
	            double tmpI = aR[i] * aI[i] * 2;
	            tmpR -= aR[n - i] * aR[n - i] - aI[n - i] * aI[n - i];
	            tmpI -= aR[n - i] * aI[n - i] * -2;
	            aR[i] = -tmpI * q;
	            aI[i] = tmpR * q;
	            aR[n - i] = aR[i];
	            aI[n - i] = -aI[i];
	        }
	        fft(true);
	        long[] ans = new long[n = na + nb - 1]; // ONLY MOD IF NEEDED
	        for (int i = 0; i < n; i++) ans[i] = Math.round(aR[i]);
	        return ans;
	    }
	    static void fft2(double[][] real, double[][] imag, boolean inv) {
	        n = real[0].length;
	        k = Integer.numberOfTrailingZeros(n);
	        
	        
	        for (int i = 0; i < real.length; i++) {
	            for (int j = 0; j < real[i].length; j++) {
	                aR[j] = real[i][j];
	                aI[j] = imag[i][j];
	            }
	            for(int j=real[i].length;j<n;j++)
	            	aR[j] = aI[j] = 0;
	            fft(inv);
	            for (int j = 0; j < real[i].length; j++) {
	            	real[i][j] = aR[j];
	                imag[i][j] = aI[j];
	                
	            }
	        }
	        n = real.length;
	        k = Integer.numberOfTrailingZeros(n);
	        
	        for (int j = 0; j < real[0].length; j++) {
	            for (int i = 0; i < real.length; i++) {
	                aR[i] = real[i][j];
	                aI[i] = imag[i][j];
	            }
	            for(int i=real.length;i<n;i++)
	            	aR[i] = aI[i] = 0;
	            fft(inv);
	            for (int i = 0; i < real.length; i++) {
	                real[i][j] = aR[i];
	                imag[i][j] = aI[i];
	            }
	        }
	        if(inv) {
		        for(int i=0;i<real.length;i++) {
		        	for(int j=0;j<real[0].length;j++) {
		        		real[i][j] /= real.length;
		        		real[i][j] /= real[0].length;
		        	}
		        }
//		        System.out.println(Arrays.deepToString(real));
	        }
	    }
	    static long[][] multiply2(long[][] a, long[][] b) {  
	        int n1 = Integer.highestOneBit(
	                Math.max(a.length, b.length) - 1) << 2;
	        int n2 = Integer.highestOneBit(
	                Math.max(a[0].length, b[0].length) - 1) << 2;
	        
//	        int max = Math.max(n1, n2);
//	        n1 = max;
//	        n2 = max;
	        n1 = Math.max(n1, 1);
	        n2 = Math.max(n2, 1);
	        
	        
	        n1 = Math.max(n1, 1);  n2 = Math.max(n2, 1);

	        double[][] ar = new double[n1][n2];
	        double[][] ai = new double[n1][n2];
	        double[][] br = new double[n1][n2];
	        double[][] bi = new double[n1][n2];
	        for (int i = 0; i < a.length; i++)
	            for(int j = 0; j < a[i].length; j++) ar[i][j] = a[i][j];
	        for (int i = 0; i < b.length; i++)
	            for(int j = 0; j < b[i].length; j++) br[i][j] = b[i][j];

	        fft2(ar, ai, false); fft2(br, bi, false);
	        for (int i = 0; i < n1; i++) {
	            for(int j = 0; j < n2; j++) {
	                double r1 = ar[i][j], r2 = br[i][j];
	                double i1 = ai[i][j], i2 = bi[i][j];
	                double real = r1 * r2 - i1 * i2;
	                ai[i][j] = (i1 * r2+ i2*r1);
	                ar[i][j] = (real);
	            }
	        }
	        fft2(ar,ai,true);  long[][] result = new long[n1][n2];
//	        System.out.println("n=" + n1 + " " + n2);
	        for (int i = 0; i < n1; i++) {
	            for(int j = 0; j < n2; j++) {
	            	int ii = i == 0 ? 0 : n1 - i;
	                result[ii][j] = Math.round(ar[i][j]);
	            }
	        }
//	        for (int i = 0; i < n1; i++) {
//	            for(int j = 0; j < n2; j++) {
//	                System.out.printf("%7d",Math.round(result[i][j]));
//	            }
//	            System.out.println();
//	        }
	        return result;
	    }
	}
	
	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner(InputStream i) {
			br = new BufferedReader(new InputStreamReader(i));
			st = new StringTokenizer("");
		}

		public String next() throws IOException {
			if (st.hasMoreTokens())
				return st.nextToken();
			else
				st = new StringTokenizer(br.readLine());
			return next();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public long nextLong() throws IOException {
			return new Long(next());
		}

		public double nextDouble() throws IOException {
			return new Double(next());
		}
	}
}