#include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;


class string_hash{
private:
    typedef long long int ll;
    typedef unsigned long long int ull;
    typedef unsigned long ul;
    typedef vector<ull> Hash;
    
    const ull mod;
    const ull roll;
    Hash H;
    string W;
    
    ull mod_pow(ull a,ull x){
        a%=mod;
        ll ans=1;
        while(x>0){
            if(x&1){ans*=a; ans%=mod;}
            a*=a; a%=mod;
            x>>=1;
        }
        return ans;
    }
    
    pll Ex_gcd(ll a,ll b){
        if(b==0){return {1,0};}
        pll ret=Ex_gcd(b,a%b);
        ret.F-=a/b*ret.S;
        return {ret.S,ret.F};
    }
    
    ull R(ull a){
        ll ret=Ex_gcd(a,mod).F;
        ret%=mod;
        if(ret<0){ret+=mod;}
        return ret;
    }
    
    void mk_hash(){
        H[0]=W[0];
        for(int i=1;i<H.size();i++){
            H[i]=H[i-1]*roll%mod+W[i];
            H[i]%=mod;
        }
    }
    
public:
    string_hash(const string &W={},ull mod=1000000007,ull roll=65537):W(W),mod(mod),roll(roll),H(W.size()){
        mk_hash();
    }
    
    void push_back(const string &A){
        ull d=H.size();
        H.resize(d+A.size());
        W.resize(d+A.size());
        for(ull i=d;i<H.size();i++){
            W[i]=A[i-d];
            H[i]=W[i];
            if(i!=0){
                H[i]+=H[i-1]*roll%mod;
            }
            H[i]%=mod;
        }
    }
    
    void push_back(char c){
        W.push_back(c);
        H.push_back(c);
        if(H.size()==1){return;}
        H[H.size()-1]+=H[H.size()-2]*roll%mod;
        H[H.size()-1]%=mod;
    }
    
    unsigned long size() const {return W.size();}
    
    const ull & MOD() const {return mod;}
    
    const ull & ROLL() const {return roll;}
    
    ull & operator [] (const ul &s){
        assert(s<H.size());
        return H[s];
    }
    
    bool operator == (string_hash &S) const {
        return S.size()==H.size() && H[H.size()-1]==S[H.size()-1];
    }
    
    //共通の長さ、初めて違う文字のインデックス
    unsigned long same(string_hash &W) const {
        ul r=min(H.size(),W.size())-1;
        if(H[r]==W[r]){return r+1;}
        ul l=0;
        while(r-l>3){
            ul m=l+(r-l)/2;
            if(W[m]!=H[m]){r=m;}
            else{l=m+1;}
        }
        for(ul i=l;i<r;i++){
            if(W[i]!=H[i]){return i;}
        }
        return r;
    }
    
    //[l,r)
    ull hash(ul l,ul r){
        assert(l<r && r<=H.size());
        if(l==0){return H[r-1];}
        return (mod+H[r-1]-H[l-1]*mod_pow(roll,r-l)%mod)%mod;
    }
    
    ull merge_hash(ull hash,ul Long){
        return (H[H.size()-1]*mod_pow(roll,Long)%mod+hash)%mod;
    }
};



template<typename T>
class vector_hash{
private:
    typedef long long int ll;
    typedef unsigned long long int ull;
    typedef unsigned long ul;
    typedef vector<ull> Hash;
    
    const ull mod;
    const ull roll;
    Hash H;
    vector<T> W;
    
    ull mod_pow(ull a,ull x){
        a%=mod;
        ll ans=1;
        while(x>0){
            if(x&1){ans*=a; ans%=mod;}
            a*=a; a%=mod;
            x>>=1;
        }
        return ans;
    }
    
    pll Ex_gcd(ll a,ll b){
        if(b==0){return {1,0};}
        pll ret=Ex_gcd(b,a%b);
        ret.F-=a/b*ret.S;
        return {ret.S,ret.F};
    }
    
    ull R(ull a){
        ll ret=Ex_gcd(a,mod).F;
        ret%=mod;
        if(ret<0){ret+=mod;}
        return ret;
    }
    
    void mk_hash(){
        H[0]=W[0]%mod;
        for(int i=1;i<H.size();i++){
            H[i]=H[i-1]*roll%mod+W[i]%mod;
            H[i]%=mod;
        }
    }
    
public:
    vector_hash(const vector<T> &W={},ull mod=1000000007,ull roll=65537):W(W),mod(mod),roll(roll),H(W.size()){
        mk_hash();
    }
    
    void push_back(const vector<T> &A){
        ull d=H.size();
        H.resize(d+A.size());
        W.resize(d+A.size());
        for(ull i=d;i<H.size();i++){
            W[i]=A[i-d];
            H[i]=W[i]%mod;
            if(i!=0){
                H[i]+=H[i-1]*roll%mod;
            }
            H[i]%=mod;
        }
    }
    
    void push_back(T c){
        W.push_back(c);
        H.push_back(c)%mod;
        if(H.size()==1){return;}
        H[H.size()-1]+=H[H.size()-2]*roll%mod;
        H[H.size()-1]%=mod;
    }
    
    unsigned long size() const {return W.size();}
    
    const ull & MOD() const {return mod;}
    
    const ull & ROLL() const {return roll;}
    
    T & operator [] (const ul &s){
        assert(s<H.size());
        return H[s];
    }
    
    bool operator == (vector_hash &S) const {
        return S.size()==H.size() && H[H.size()-1]==S[H.size()-1];
    }
    
    //共通の長さ、初めて違う文字のインデックス
    unsigned long same(vector_hash &W) const {
        ul r=min(H.size(),W.size())-1;
        if(H[r]==W[r]){return r+1;}
        ul l=0;
        while(r-l>3){
            ul m=l+(r-l)/2;
            if(W[m]!=H[m]){r=m;}
            else{l=m+1;}
        }
        for(ul i=l;i<r;i++){
            if(W[i]!=H[i]){return i;}
        }
        return r;
    }
    
    //[l,r)
    ull hash(ul l,ul r){
        assert(l<r && r<=H.size());
        if(l==0){return H[r-1];}
        return (mod+H[r-1]-H[l-1]*mod_pow(roll,r-l)%mod)%mod;
    }
    
    ull merge_hash(ull hash,ul Long){
        return (H[H.size()-1]*mod_pow(roll,Long)%mod+hash)%mod;
    }
};

class Find{
private:
    set<pll> Q;
    
public:
    Find(ll h,ll w,ll r,ll c,ull mod1,ull mod2,vector<string> &S,vector<string> &P,ull Y,ull X){
        vector<ull> F(r);
        for(int i=0;i<r;i++){
            string_hash S(P[i],mod1,X);
            F[i]=S[S.size()-1];
        }
        vector_hash<ull> A(F,mod2,Y);
        ull k=A[A.size()-1];
        vector<vector<ull>> dp(w,vector<ull>(h,0));
        for(int i=0;i<S.size();i++){
            string_hash a(S[i],mod1,X);
            for(ll t=c-1;t<w;t++){
                dp[t][i]=a.hash(t-c+1,t+1);
            }
        }
        for(int i=0;i<w;i++){
            vector_hash<ull> a(dp[i],mod2,Y);
            for(ll t=r-1;t<h;t++){
                dp[i][t]=a.hash(t-r+1,t+1);
            }
        }
        for(ll i=r-1;i<h;i++){
            for(ll t=c-1;t<w;t++){
                if(dp[t][i]==k){
                    Q.insert({i,t});
                    //{i-r+1,t-c+1}
                }
            }
        }
    }
    
    bool is(ll a,ll b){
        return Q.find({a,b})!=Q.end();
    }
};


int main(){
    random_device rand;
    mt19937 mt(rand());
    uniform_int_distribution<int> R(100,MOD-1);
    ll h,w;
    cin>>h>>w;
    vector<string> S(h);
    for(int i=0;i<h;i++){
        cin>>S[i];
    }
    ll r,c;
    cin>>r>>c;
    vector<ull> F(r);
    vector<string> Q(r);
    for(int i=0;i<r;i++){
        cin>>Q[i];
    }
    Find A(h,w,r,c,1001832439,1001821259,S,Q,R(mt),R(mt)),B(h,w,r,c,1001628343,1001703679,S,Q,R(mt),R(mt)),C(h,w,r,c,MOD,1002075103,S,Q,R(mt),R(mt));
    for(ll i=r-1;i<h;i++){
        for(ll t=c-1;t<w;t++){
            if(A.is(i,t) && B.is(i,t) && C.is(i,t)){
                cout<<i-r+1<<" "<<t-c+1<<endl;
            }
        }
    }
    
    
    return 0;
}



Measured memory_bytes: 105768