Problem:
Pattern Search
Find places where a
R
×
C
pattern is found within a
H
×
W
region. Print top-left coordinates (
i
,
j
) of sub-regions where the pattern found. The top-left and bottom-right coordinates of the region is (0, 0) and (
H
-1,
W
-1) respectively.
Input
In the first line, two integers
H
and
W
are given. In the following
H
lines,
i
-th lines of the region are given.
In the next line, two integers
R
and
C
are given. In the following
R
lines,
i
-th lines of the pattern are given.
output
For each sub-region found, print a coordinate
i
and
j
separated by a space character in a line. Print the coordinates in ascending order of the row numbers (
i
), or the column numbers (
j
) in case of a tie.
Constraints
1 ≤
H, W
≤ 1000
1 ≤
R, C
≤ 1000
The input consists of alphabetical characters and digits
Sample Input 1
4 5
00010
00101
00010
00100
3 2
10
01
10
Sample Output 1
0 3
1 2

Submitted solutions:

code_snippet: #include<iostream>
#include<vector>
#include<string>
using namespace std;
using ull = unsigned long long;
#define D1 1000000007
#define D2 2000000011

int main(){
	int H, W;
	cin >> H >> W;
	vector<string> str(H);
	for(auto& i : str) cin >> i;
	int R, C;
	cin >> R >> C;
	if(R > H || C > W) return 0;
	vector<string> pt(R);
	for(auto& i : pt) cin >> i;
	vector<ull> ph1(R, 0), ph2(ph1), sh1(R), sh2(R);
	ull n1 = 1, n2 = 1;
	for(int i = 0; i < C; i++){
		n1 *= D1, n2 *= D2;
		ph1[0] = ph1[0] * D1 + pt[0][i];
		ph2[0] = ph2[0] * D2 + pt[0][i];
	}
	for(int i = 1; i < R; i++){
		for(int j = 0; j < C; j++){
			ph1[i] = ph1[i] * D1 + pt[i][j];
			ph2[i] = ph2[i] * D2 + pt[i][j];
		}
	}
	
	for(int k = 0, t1 = H - R + 1, t2 = W - C + 1; k < t1; k++){
		bool iscur = true;
		sh1.assign(R, 0);
		sh2.assign(R, 0);
		for(int i = 0; i < R; i++){
			for(int j = 0; j < C; j++){
				sh1[i] = sh1[i] * D1 + str[k + i][j];
				sh2[i] = sh2[i] * D2 + str[k + i][j];
			}
			if(sh1[i] != ph1[i] || sh2[i] != ph2[i]) iscur = false; 
		}
		if(iscur) cout << k << ' ' << 0 << endl;
		for(int l = 1; l < t2; l++){
			iscur = true;
			for(int i = 0; i < R; i++){
				sh1[i] = sh1[i] * D1 - str[i + k][l - 1] * n1 + str[i + k][l + C - 1];
				sh2[i] = sh2[i] * D2 - str[i + k][l - 1] * n2 + str[i + k][l + C - 1];
				if(sh1[i] != ph1[i] || sh2[i] != ph2[i]) iscur = false; 
			}
			if(iscur) cout << k << ' ' << l << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 830
memory_kb: 7296
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;
string s[1005],t[1005];
ll pre[1005][1005];
ll pre2[1005][1005];
ll mp[1005];
ll mq[1005];
int n1,m1,n2,m2;
ll p=131,q=233;
ll Q=1e9+7;
void solve(){
	mp[0]=mq[0]=1;
	for(int i=1;i<=1000;i++){
		mp[i]=mp[i-1]*p%Q;
		mq[i]=mq[i-1]*q%Q;
	}
	for(int i=1;i<=n1;i++){
		for(int j=1;j<=m1;j++){
			pre[i][j]=(-pre[i-1][j-1]*p*q+pre[i-1][j]*p+pre[i][j-1]*q+s[i-1][j-1])%Q;
			pre[i][j]=(pre[i][j]+Q)%Q;
		}
	}
	for(int i=1;i<=n2;i++){
		for(int j=1;j<=m2;j++){
			pre2[i][j]=(-pre2[i-1][j-1]*p*q+pre2[i-1][j]*p+pre2[i][j-1]*q+t[i-1][j-1])%Q;
			pre2[i][j]=(pre2[i][j]+Q)%Q;
		}
	}
	ll hs=pre2[n2][m2];
	for(int i=1;i<=n1-n2+1;i++){
		for(int j=1;j<=m1-m2+1;j++){
			ll v=(pre[i+n2-1][j+m2-1]+pre[i-1][j-1]*mp[n2]%Q*mq[m2]%Q-pre[i+n2-1][j-1]*mq[m2]%Q-pre[i-1][j+m2-1]*mp[n2]%Q)%Q;
			v=(v+Q)%Q;
			if(v==hs){
				cout<<i-1<<' '<<j-1<<"\n";
			}
		}
	}	
}
int main(){
//	freopen("a.txt","r",stdin);
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n1>>m1;
	for(int i=0;i<n1;i++)cin>>s[i];
	cin>>n2>>m2;
	for(int i=0;i<n2;i++)cin>>t[i];
	solve();	
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 21260
final_rank: 2

code_snippet: #include <iostream>
#include <string>
#include <vector>

#define BASE0 (long long)2549
#define BASE1 (long long)4283
#define MOD (long long)1000000007

/*
* @brief 文字列のハッシュを生成
* 
* @param [in] vField 元の2次元文字列
* @param [in] fieldHeight 2次元文字列の高さ
* @param [in] fieldWidth  2次元文字列の長さ
* @param [in] powHeight 2次元文字列の高さ分BASE0を累乗した配列
* @param [in] powWidth  2次元文字列の長さ分BASE1を累乗した配列
* @returns ハッシュ値を持つ2次元配列
*/
std::vector<std::vector<long long>> MakeHash(const std::vector<std::string>& vField, int fieldHeight, int fieldWidth, const std::vector<long long>& powHeight, const std::vector<long long>& powWidth)
{
	std::vector<std::vector<long long>> vHashedField(fieldHeight + 1, std::vector<long long>(fieldWidth + 1, 0));

	for (int i = 0;i < fieldHeight;i++)
	{
		for (int j = 0;j < fieldWidth;j++)
		{
			vHashedField[i + 1][j + 1] = (vField[i][j] * powHeight[i] % MOD * powWidth[j] % MOD + vHashedField[i][j + 1] + vHashedField[i + 1][j] - vHashedField[i][j] + MOD) % MOD;
		}
	}

	return vHashedField;
}

/*
* @brief 文字フィールドから検索パターンと一致する箇所を出力する
* 
* @param [in] vHashedField   文字列フィールドのハッシュ値
* @param [in] vHashedPattern 検索パターンのハッシュ値
* @param [in] fieldHeight 2次元文字列の高さ
* @param [in] fieldWidth  2次元文字列の長さ
* @param [in] fieldHeight 2次元パターンの高さ
* @param [in] fieldWidth  2次元パターンの長さ
* @param [in] powHeight 2次元文字列の高さ分BASE0を累乗した配列
* @param [in] powWidth  2次元文字列の長さ分BASE1を累乗した配列
*/
void OutputMatchPatternIndex(const std::vector<std::vector<long long>>& vHashedField, const std::vector<std::vector<long long>>& vHashedPattern, int fieldHeight, int fieldWidth, int patternRow, int patternColumn, const std::vector<long long>& powHeight, const std::vector<long long>& powWidth)
{
	int numSearchRow = fieldHeight - patternRow + 1;
	int numSearchColumn = fieldWidth - patternColumn + 1;

	for (int fri = 0;fri < numSearchRow;fri++)
	{
		for (int fci = 0;fci < numSearchColumn;fci++)
		{
			int pr = patternRow, pc = patternColumn;
			long long hashedFieldValue = (vHashedField[fri + pr][fci + pc] - vHashedField[fri][fci + pc] + MOD - vHashedField[fri + pr][fci] + MOD + vHashedField[fri][fci]) % MOD;
			long long hashedPatternValue = vHashedPattern[pr][pc] * powHeight[fri] % MOD * powWidth[fci] % MOD;

			if (hashedFieldValue == hashedPatternValue)
			{
				std::cout << fri << " " << fci << std::endl;
			}
		}
	}

	return;
}

int main()
{
	int fieldHeight, fieldWidth;
	std::cin >> fieldHeight >> fieldWidth;

	std::vector<std::string> vField(fieldHeight);
	for (int i = 0;i < fieldHeight;i++)
	{
		std::cin >> vField[i];
	}
	
	int patternRow, patternColumn;
	std::cin >> patternRow >> patternColumn;

	std::vector<std::string> vPattern(patternRow);
	for (int i = 0;i < patternRow;i++)
	{
		std::cin >> vPattern[i];
	}

	std::vector<long long> powHeight(fieldHeight), powWidth(fieldWidth);
	powHeight[0] = 1;
	powWidth[0] = 1;

	for (int i = 1;i < fieldHeight;i++)
	{
		powHeight[i] = (powHeight[i - 1] * BASE0) % MOD;
	}

	for (int i = 1;i < fieldWidth;i++)
	{
		powWidth[i] = (powWidth[i - 1] * BASE1) % MOD;
	}

	std::vector<std::vector<long long>> vHashedField   = MakeHash(vField,   fieldHeight, fieldWidth,    powHeight, powWidth);
	std::vector<std::vector<long long>> vHashedPattern = MakeHash(vPattern, patternRow,  patternColumn, powHeight, powWidth);

	OutputMatchPatternIndex(vHashedField, vHashedPattern, fieldHeight, fieldWidth, patternRow, patternColumn, powHeight, powWidth);

	return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 22508
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep2(i,a,b) for (int i = (int)(a); i < (int)(b); i++)
#define all(v) v.begin(),v.end()
#define inc(x,l,r) ((l)<=(x)&&(x)<(r)) 
#define Unique(x) sort(all(x)), x.erase(unique(all(x)), x.end())
#define pcnt __builtin_popcountll
#define pb push_back
typedef long long ll;
#define int ll
using ld = long double;
//using ld = __float128;
using vi = vector<int>;
using vs = vector<string>;
using P = pair<int,int>;
using vp = vector<P>;
using ull = unsigned long long;
template<typename T1,typename T2> bool chmax(T1 &a, const T2 b) {if (a < b) {a = b; return true;} else return false; }
template<typename T1,typename T2> bool chmin(T1 &a, const T2 b) {if (a > b) {a = b; return true;} else return false; }
template<typename T> using priority_queue_greater = priority_queue<T, vector<T>, greater<T>>;
template<typename T> istream &operator>>(istream& is,vector<T> &v){for(T &in:v)is>>in;return is;}
template<class... T> void input(T&... a){(cin>> ... >> a);}
#ifdef LOCAL
template<typename T> ostream &operator<<(ostream &os,const vector<T> &v){os<<"\x1b[32m";rep(i,v.size())os<<v[i]<<(i+1!=v.size()?" ":"");os<<"\x1b[0m";return os;}
template<class T> int print(T& a){cout << "\x1b[32m"<< a<< '\n' << "\x1b[0m";return 0;}
template<class T,class... Ts> int print(const T&a, const Ts&... b){cout << "\x1b[32m" << a;(cout<<...<<(cout<<' ',b));cout<<'\n' << "\x1b[0m";return 0;}
#else
template<typename T> ostream &operator<<(ostream &os,const vector<T> &v){rep(i,v.size())os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<class T> int print(T& a){cout << a<< '\n';return 0;}
template<class T,class... Ts> int print(const T&a, const Ts&... b){cout << a;(cout<<...<<(cout<<' ',b));cout<<'\n';return 0;}
#endif
#define VI(v,n) vi v(n); input(v)
#define INT(...) int __VA_ARGS__; input(__VA_ARGS__)
struct __m___m__ {__m___m__(){cin.tie(0);ios_base::sync_with_stdio(false);cout << fixed << setprecision(20);}} _m_m_;
int di[]={0,1,0,-1,-1,-1,1,1};
int dj[]={1,0,-1,0,-1,1,-1,1};
const ll INF = 8e18;
//mint stom(const string &s,int b=10){mint res = 0;for(auto c:s)res *= b,res += c-'0';return res;}
uint32_t xor128() {
    static uint32_t x = 123456789,y = 362436069,z = 521288629,w = 88675123;
    uint32_t t;
    t = x ^ (x << 11);x = y; y = z; z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
ll randint(ll mn,ll mx){
    return xor128()%(mx+1-mn)+mn;
}
using ull = unsigned long long;
const ull mod = 0x1fffffffffffffff;
const ull base1 = chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now().time_since_epoch()).count() %mod;
const ull base2 = (base1 + 1123581321)%mod;
struct RollingHash2D {
    int H, W;
    vector<vector<ull>> hash;
    vector<ull> pow1, pow2;

    inline ull mul(ull a, ull b) const {
        __uint128_t ans = __uint128_t(a) * b;
        ans = (ans >> 61) + (ans & mod);
        if (ans >= mod) ans -= mod;
        return ans;
    }
    RollingHash2D(const vector<vector<ll>>& grid) {
        init(grid);
    }
    RollingHash2D(const vector<string>& grid) {
        H = grid.size();
        W = grid[0].size();
        vector numGrid(H, vector<ll>(W));
        rep(i,H)rep(j,W)numGrid[i][j] = grid[i][j];
        init(numGrid);
    }

    void init(const vector<vector<ll>>& grid) {
        H = grid.size();
        W = grid[0].size();
        hash.assign(H + 1, vector<ull>(W + 1, 0));
        pow1.assign(H + 1, 1);
        pow2.assign(W + 1, 1);
        rep(i,H) pow1[i+1] = mul(pow1[i], base1);
        rep(j,W) pow2[j+1] = mul(pow2[j], base2);
        rep(i,H)rep(j,W){
            hash[i+1][j+1] = grid[i][j];
            hash[i+1][j+1] += mul(hash[i+1][j], base2);
            hash[i+1][j+1] %= mod;
            hash[i+1][j+1] += mul(hash[i][j+1], base1);
            hash[i+1][j+1] %= mod;
            hash[i+1][j+1] += mod - mul(hash[i][j], mul(base1, base2));
            hash[i+1][j+1] %= mod;
        }
    }

    ull get(int li, int lj, int ri, int rj) {
        ull res = hash[ri][rj];
        res += mod - mul(hash[li][rj], pow1[ri-li]);
        res %= mod;
        res += mod - mul(hash[ri][lj], pow2[rj-lj]);
        res %= mod;
        res += mul(hash[li][lj], mul(pow1[ri-li], pow2[rj-lj]));
        res %= mod;
        return res;
    }
};

signed main() {
    INT(h,w);
    vs s(h);cin>>s;
    INT(r,c);
    vs t(r);cin>>t;
    RollingHash2D rs(s), rt(t);
    rep(i,h-r+1)rep(j,w-c+1){
        if(rs.get(i,j,i+r,j+c) == rt.get(0,0,r,c))print(i,j);
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 28868
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
typedef unsigned long long ull;
const int N = 1e3 + 5;
const ull p1 = 257, p2 = 1e7 + 7;

string s1[N], s2[N];
ull res, d2[N][N], d1[N][N];

void solve() {
    int h1, h2, w1, w2;
    cin >> h1 >> w1;
    rep(i, h1) cin >> s1[i];
    cin >> h2 >> w2;
    rep(i, h2) cin >> s2[i];

    for (int i = 0; i < h2; i++) {
        ull t = 0;
        for (int j = 0; j < w2; j++) t = t * p1 + s2[i][j];
        res = res * p2 + t;
    }

    ull C = 1;
    for (int i = 0; i < w2; i++) C *= p1;
    for (int i = 0; i < h1; i++) {
        ull key = 0;
        for (int j = 0; j < w1; j++) {
            key = key * p1 + s1[i][j];
            if (j >= w2) key -= s1[i][j - w2] * C;
            d2[i][j] = d1[i][j] = key;
        }
    }

    C = 1;
    for (int i = 0; i < h2; i++) C *= p2;
    for (int i = 1; i < h1; i++) {
        for (int j = 0; j < w1; j++) {
            d1[i][j] = d1[i - 1][j] * p2 + d1[i][j];
            if (i >= h2) d1[i][j] -= d2[i - h2][j] * C;
        }
    }

    for (int i = h2 - 1; i < h1; i++) {
        for (int j = w2 - 1; j < w1; j++) {
            if (d1[i][j] == res) cout << i - h2 + 1 << " " << j - w2 + 1 << endl;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 21172
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
constexpr ull MOD=(1UL<<61)-1;
ull add(ull a,ull b){
  ull res=a+b;
  if(res>=MOD)res-=MOD;
  return res;
}
ull dec(ull a,ull b){return add(a,MOD-b);}
ull mul(ull a,ull b){
  __uint128_t t=(__uint128_t)a*(__uint128_t)b;
  t=(t>>61)+(t&MOD);
  if(t>=MOD)return (ull)(t-MOD);
  return (ull)t;
}
constexpr int ma=1000000;
constexpr ull base=2191546160808601280UL;
constexpr ull baseinv=250865457956280347UL;
array<ull,ma+1>tab;
array<ull,ma+1>tabinv;
int main() {
  std::cin.tie(nullptr);
  std::ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(16);
  tab[0]=1UL;tabinv[0]=1UL;
  rep(i,ma){tab[i+1]=mul(tab[i],base);tabinv[i+1]=mul(tabinv[i],baseinv);}
  int H;int W;cin>>H>>W;
  vector<string>S(H);
  rep(i,H)cin>>S[i];
  int R;int C;cin>>R>>C;
  if(R>H||C>W)return 0;
  vector<string>T(R);
  rep(i,R)cin>>T[i];
  vector<vector<ull>>S0(H+1,vector<ull>(W+1));
  rep(i,H){
    rep(j,W)S0[i+1][j+1]=mul((ull)S[i][j],tab[i*C+j]);
  }
  rep(i,H){
    rep(j,W){S0[i+1][j+1]+=S0[i+1][j];if(S0[i+1][j+1]>=MOD)S0[i+1][j+1]-=MOD;}
  }
  rep(i,H){
    rep(j,W){S0[i+1][j+1]+=S0[i][j+1];if(S0[i+1][j+1]>=MOD)S0[i+1][j+1]-=MOD;}
  }
  ull T0=0UL;
  int i0=0;
  rep(i,R){
    rep(j,C){
      T0+=mul((ull)T[i][j],tab[i0]);
      if(T0>=MOD)T0-=MOD;
      i0++;
    }
  }
  rep(i,H-R+1){
    rep(j,W-C+1){
      if(T0==mul(dec(add(S0[i+R][j+C],S0[i][j]),add(S0[i][j+C],S0[i+R][j])),tabinv[i*C+j])){
	cout<<i<<' '<<j<<'\n';
      }
    }
  }
}
accuracy: 1
time_ms: 40
memory_kb: 29000
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <string>
using namespace std;

// 1次元KMP法のための部分一致テーブル (LPS) を構築
vector<int> computeLPSArray(const string& pattern) {
    int M = pattern.size();
    vector<int> lps(M);
    int length = 0; // 最長の部分一致の長さ
    lps[0] = 0; // 初期値

    // パターンの2文字目から末尾までを処理
    int i = 1;
    while (i < M) {
        if (pattern[i] == pattern[length]) {
            length++;
            lps[i] = length;
            i++;
        } else {
            if (length != 0) {
                length = lps[length - 1];
            } else {
                lps[i] = 0;
                i++;
            }
        }
    }
    return lps;
}

// 2次元フィールドに対するKMP法
void KMP2D(const vector<string>& field, const vector<string>& pattern, int H, int W, int R, int C) {
    // 各行に対して部分一致テーブルを作成 (1次元KMPの前処理)
    vector<vector<int>> lps(R);
    for (int i = 0; i < R; ++i) {
        lps[i] = computeLPSArray(pattern[i]);
    }

    // フィールド内でパターンを探索
    for (int i = 0; i <= H - R; ++i) {
        vector<int> match_row(W, 0); // 各列で一致する行数を追跡
        for (int row = 0; row < R; ++row) {
            // 1次元KMP法で行ごとにパターンを探索
            int j = 0; // フィールド内の列位置
            int k = 0; // パターン内の列位置
            while (j < W) {
                if (field[i + row][j] == pattern[row][k]) {
                    j++;
                    k++;
                    if (k == C) {
                        match_row[j - C]++; // パターンの全行が一致する候補の開始列
                        k = lps[row][k - 1]; // 部分一致情報を利用
                    }
                } else {
                    if (k != 0) {
                        k = lps[row][k - 1];
                    } else {
                        j++;
                    }
                }
            }
        }

        // 各列で全行一致するか確認
        for (int col = 0; col <= W - C; ++col) {
            if (match_row[col] == R) {
                // R行すべてで一致するので位置を報告
                cout << i << " " << col << endl;
            }
        }
    }
}

int main() {
    // 入力の読み取り
    int H, W;
    cin >> H >> W;
    vector<string> field(H);
    for (int i = 0; i < H; ++i) {
        cin >> field[i];
    }

    int R, C;
    cin >> R >> C;
    vector<string> pattern(R);
    for (int i = 0; i < R; ++i) {
        cin >> pattern[i];
    }

    // 2次元KMP法でフィールド内のパターンを探索
    KMP2D(field, pattern, H, W, R, C);

    return 0;
}
accuracy: 1
time_ms: 750
memory_kb: 10984
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
const ulong BASE = 31;
const ulong MASK30 = (1ull << 30) -1;
const ulong MASK31 = (1ull << 31) -1;
const ulong MOD = (1ull << 61) -1;
const ulong MASK61 = MOD;
const ulong POSITIZER = MOD*4;

ulong Pow = 1;

ulong convert_int(char c){
    ulong ans;
    if('a' <= c && c <= 'z'){
        ans = c - 'a' + 1;
    }
    else if('A' <= c && c <= 'Z'){
        ans = c - 'A' + 27;
    }
    else{
        ans = c - '0' + 52;
    }
    return ans; 
}
ulong Mul(ulong a,ulong b){
    ulong au = a >> 31;
    ulong bu = b >> 31;
    ulong ad = a & MASK31;
    ulong bd = b & MASK31;
    ulong mid = ad*bu + bd*au;
    ulong midu = mid >> 30;
    ulong midd = mid & MASK30;
    return 2*au*bu + midu + (midd<<31) + ad*bd;
}

ulong CalcMod(ulong x){
    ulong xu = x >> 61;
    ulong xd = x & MASK61;
    ulong res = xu + xd;
    if(res >= MOD){
        res -= MOD;
    }
    return res;
}

int main(){
    int h,w;
    cin >> h >> w;
    vector<pair<int,int>> ans;
    vector<vector<char>> field(h,vector<char>(w+1));
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            cin >> field[i][j];
        }
    }
    int r,c;
    cin >> r >> c;
    vector<vector<char>> pattern(r,vector<char>(c+1));
    vector<ulong> pattern_key(r);
    for(int i = 0; i < r; i++){
        for(int j = 0; j < c; j++){
            cin >> pattern[i][j];
        }
    }
    for(int i = 0; i < r; i++){
        ulong hash = convert_int(pattern[i][0]);
        for(int j = 1; j < c; j++){
            ulong second_hash = convert_int(pattern[i][j]);
            hash = CalcMod(Mul(hash,BASE) + second_hash);
        }
        pattern_key[i] = hash;
    }
    for(int i = 0; i < c; i++){
        Pow  = CalcMod(Mul(Pow,BASE));
    }
    vector<vector<ulong>> Hash(h,vector<ulong>(w+1));
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            ulong c = convert_int(field[i][j]);
            if(j==0) Hash[i][j+1] = c;
            else Hash[i][j+1] = CalcMod(Mul(Hash[i][j],BASE) + c);
        }
    }
    for(int i = 0; i <= h-r; i++){
        for(int j = 0; j <= w-c; j++){
            bool result = true;
            for(int l = 0; l < r; l++){
                ulong search_hash = CalcMod(Hash[i+l][j+c] + POSITIZER - Mul(Hash[i+l][j],Pow));
                if(search_hash!=pattern_key[l]){
                    result = false;
                    break;
                }
            }
            if(result){
                ans.push_back({i,j});
            }
        }
    }
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i].first << " " << ans[i].second << endl;
    }
}
accuracy: 1
time_ms: 1340
memory_kb: 17832
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
const string dl = "\n";
typedef unsigned long long ll;
const ll B = 1e9 + 7;
/*
Let's discuss how string hashing works:
1. We have a string s of length n.
2. We have a base B.
3. We have a prime p.
4. We have a hash array h of length n.

we represent the string s as a number in base B, under modulo p.
that is the string is letters abcde will look like this:
\( a * B^4 + b * B^3 + c * B^2 + d * B^1 + e * B^0 \) mod p
so we build the array h as follows (one-based):
\( h[1] = s[1] \)
\( h[i] = (h[i-1] * B + s[i]) mod p \) mod p for all i from 2 to n.
Now, to get a substring hash, it is easy as getting using prefix sums to get the sum of a range of numbers.
We use the following formula to get the hash of a substring from l to r:
\( h[l,r] = h[r] - h[l-1] * B^{r-l+1} \) mod p, that is we divide by the base raised to the power of the length of the substring, that is similar to shifting the number to the right by the length of the substring.

char(31) =

With that said, let's read the input, and start coding the solution.
*/

int main()
{

    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    ll H, W, R, C;
    cin >> H >> W;
    vector<string> grid(H);
    for (int i = 0; i < H; i++)
        cin >> grid[i];

    cin >> R >> C;
    vector<string> pattern(R);
    for (int i = 0; i < R; i++)
        cin >> pattern[i];

    if (H < R || W < C)
    {
        return 0;
    }

    vector<vector<ll>> grid_hash(H, vector<ll>(W + 1));
    vector<vector<ll>> pattern_hash(R, vector<ll>(C + 1));
    vector<ll> power(W + 1);
    power[0] = 1;
    for (int i = 1; i <= W; i++)
        power[i] = (power[i - 1] * B);

    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j < W; j++)
        {
            grid_hash[i][j + 1] = (grid_hash[i][j] * B + grid[i][j]);
        }
    }

    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            pattern_hash[i][j + 1] = (pattern_hash[i][j] * B + pattern[i][j]);
        }
    }

    auto query = [&](int i, int l, int r)
    {
        return (grid_hash[i][r] - grid_hash[i][l - 1] * power[r - l + 1]);
    };

    vector<vector<ll>> preCalcQuery(H, vector<ll>(W - C + 1));
    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j <= W - C; j++)
        {
            preCalcQuery[i][j] = query(i, j + 1, j + C);
        }
    }
    for (int i = 0; i <= H - R; i++)
    {
        for (int j = 0; j <= W - C; j++)
        {
            bool found = true;
            for (int k = 0; k < R; k++)
            {
                if (preCalcQuery[i + k][j] != pattern_hash[k][C])
                {
                    found = false;
                    break;
                }
            }
            if (found)
                cout << i << " " << j << dl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 21284
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
const string dl = "\n";
typedef unsigned long long ll;
const ll B = 1e9 + 7;
/*
Let's discuss how string hashing works:
1. We have a string s of length n.
2. We have a base B.
3. We have a prime p.
4. We have a hash array h of length n.

we represent the string s as a number in base B, under modulo p.
that is the string is letters abcde will look like this:
\( a * B^4 + b * B^3 + c * B^2 + d * B^1 + e * B^0 \) mod p
so we build the array h as follows (one-based):
\( h[1] = s[1] \)
\( h[i] = (h[i-1] * B + s[i]) mod p \) mod p for all i from 2 to n.
Now, to get a substring hash, it is easy as getting using prefix sums to get the sum of a range of numbers.
We use the following formula to get the hash of a substring from l to r:
\( h[l,r] = h[r] - h[l-1] * B^{r-l+1} \) mod p, that is we divide by the base raised to the power of the length of the substring, that is similar to shifting the number to the right by the length of the substring.

char(31) =

With that said, let's read the input, and start coding the solution.
*/

int main()
{

    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    ll H, W, R, C;
    cin >> H >> W;
    vector<string> grid(H);
    for (int i = 0; i < H; i++)
        cin >> grid[i];

    cin >> R >> C;
    vector<string> pattern(R);
    for (int i = 0; i < R; i++)
        cin >> pattern[i];

    vector<vector<ll>> grid_hash(H, vector<ll>(W + 1));
    vector<vector<ll>> pattern_hash(R, vector<ll>(C + 1));
    vector<ll> power(W + 1);
    power[0] = 1;
    for (int i = 1; i <= W; i++)
        power[i] = (power[i - 1] * B);

    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j < W; j++)
        {
            grid_hash[i][j + 1] = (grid_hash[i][j] * B + grid[i][j]);
        }
    }

    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            pattern_hash[i][j + 1] = (pattern_hash[i][j] * B + pattern[i][j]);
        }
    }

    auto query = [&](int i, int l, int r)
    {
        return (grid_hash[i][r] - grid_hash[i][l - 1] * power[r - l + 1]);
    };

    vector<vector<ll>> preCalcQuery(H, vector<ll>(W - C + 1));
    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j <= W - C; j++)
        {
            preCalcQuery[i][j] = query(i, j + 1, j + C);
        }
    }
    for (int i = 0; i <= H - R; i++)
    {
        for (int j = 0; j <= W - C; j++)
        {
            bool found = true;
            for (int k = 0; k < R; k++)
            {
                if (preCalcQuery[i + k][j] != pattern_hash[k][C])
                {
                    found = false;
                    break;
                }
            }
            if (found)
                cout << i << " " << j << dl;
        }
    }
    return 0;
}
accuracy: 0.8333333333333334
time_ms: 320
memory_kb: 21268
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define ALL(A) A.begin(),A.end()
ll f(char c){
    if('0'<=c&&c<='9')return c-'0';
    if('a'<=c&&c<='z')return 10+c-'a';
    return 36+c-'A';
}
int main(){
    int H,W;cin>>H>>W;
    vector<string>S(H);
    REP(i,H)cin>>S[i];
    int h,w;cin>>h>>w;
    vector<string>T(h);
    if(h>H||w>W)return 0;
    REP(i,h)cin>>T[i];
    srand(time(NULL));
    ll base=rand();
    const vi mod={998244353,1000000007,1000000009};
    vvvi P(3,vvi(H,vi(W)));
    vi s={1,1,1};
    REP(i,H)REP(j,W){
        REP(_,3)P[_][i][j]=s[_];
        REP(_,3)s[_]=s[_]*base%mod[_];
    }
    vvvi A(3,vvi(H+1,vi(W+1)));
    REP(_,3)REP(i,H)REP(j,W)A[_][i+1][j+1]=(A[_][i+1][j]+A[_][i][j+1]-A[_][i][j]+f(S[i][j])*P[_][i][j])%mod[_];
    vi hash(3);
    REP(_,3)REP(i,h)REP(j,w){
        hash[_]+=P[_][i][j]*f(T[i][j]);
        hash[_]%=mod[_];
    }
    REP(i,H-h+1)REP(j,W-w+1){
        vi val(3);
        REP(_,3)val[_]=A[_][i+h][j+w]-A[_][i][j+w]-A[_][i+h][j]+A[_][i][j];
        REP(_,3)val[_]=(val[_]%mod[_]+mod[_])%mod[_];
        bool ok=1;
        REP(_,3)if((P[_][i][j]*hash[_]-val[_])%mod[_])ok=0;
        if(ok)cout<<i<<" "<<j<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 61952
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define ALL(A) A.begin(),A.end()
ll f(char c){
    if('0'<=c&&c<='9')return c-'0';
    if('a'<=c&&c<='z')return 10+c-'a';
    return 36+c-'A';
}
int main(){
    int H,W;cin>>H>>W;
    vector<string>S(H);
    REP(i,H)cin>>S[i];
    int h,w;cin>>h>>w;
    vector<string>T(h);
    REP(i,h)cin>>T[i];
    srand(time(NULL));
    ll base=rand();
    const vi mod={998244353,1000000007,1000000009};
    vvvi P(3,vvi(H,vi(W)));
    vi s={1,1,1};
    REP(i,H)REP(j,W){
        REP(_,3)P[_][i][j]=s[_];
        REP(_,3)s[_]=s[_]*base%mod[_];
    }
    vvvi A(3,vvi(H+1,vi(W+1)));
    REP(_,3)REP(i,H)REP(j,W)A[_][i+1][j+1]=(A[_][i+1][j]+A[_][i][j+1]-A[_][i][j]+f(S[i][j])*P[_][i][j])%mod[_];
    vi hash(3);
    REP(_,3)REP(i,h)REP(j,w){
        hash[_]+=P[_][i][j]*f(T[i][j]);
        hash[_]%=mod[_];
    }
    REP(i,H-h+1)REP(j,W-w+1){
        vi val(3);
        REP(_,3)val[_]=A[_][i+h][j+w]-A[_][i][j+w]-A[_][i+h][j]+A[_][i][j];
        REP(_,3)val[_]=(val[_]%mod[_]+mod[_])%mod[_];
        bool ok=1;
        REP(_,3)if((P[_][i][j]*hash[_]-val[_])%mod[_])ok=0;
        if(ok)cout<<i<<" "<<j<<endl;
    }
    return 0;
}
accuracy: 0.8333333333333334
time_ms: 480
memory_kb: 61804
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;

ull M1=1000000007;
ull M2=9973;

int main(){
  int h,w,r,c;
  cin >> h >> w;
  vector<string> s(h);
  for(int i=0;i<h;i++) cin >> s[i];
  cin >> r >> c;
  vector<string> t(r);
  for(int i=0;i<r;i++) cin >> t[i];
  
  vector hs(h+1,vector<ull>(w+1,0));
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
    }
    for(int j=0;j<w;j++){
      hs[i+1][j+1]+=hs[i][j+1]*M2;
    }
  }
  ull ht=0;
  for(int i=0;i<r;i++){
    ull ht1=0;
    for(int j=0;j<c;j++){
      ht1=ht1*M1+t[i][j];
    }
    ht=ht*M2+ht1;
  }
  
  ull Mr=1,Mc=1;
  for(int i=0;i<r;i++) Mr*=M2;
  for(int j=0;j<c;j++) Mc*=M1;
  
  for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      ull h1=hs[i+r][j+c]-hs[i+r][j]*Mc;
      ull h2=hs[i][j+c]-hs[i][j]*Mc;
      ull hss=h1-h2*Mr;
      if( hss==ht) cout << i << " " << j << endl;
    }
  }
  
}
accuracy: 1
time_ms: 380
memory_kb: 14520
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;

ull M1=1000000007;
ull M2=998244353;

int main(){
  int h,w,r,c;
  cin >> h >> w;
  vector<string> s(h);
  for(int i=0;i<h;i++) cin >> s[i];
  cin >> r >> c;
  vector<string> t(r);
  for(int i=0;i<r;i++) cin >> t[i];
  
  vector hs(h+1,vector<ull>(w+1,0));
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
    }
    for(int j=0;j<w;j++){
      hs[i+1][j+1]+=hs[i][j+1]*M2;
    }
  }
  ull ht=0;
  for(int i=0;i<r;i++){
    ull ht1=0;
    for(int j=0;j<c;j++){
      ht1=ht1*M1+t[i][j];
    }
    ht=ht*M2+ht1;
  }
  
  ull Mr=1,Mc=1;
  for(int i=0;i<r;i++) Mr*=M2;
  for(int j=0;j<c;j++) Mc*=M1;
  
  for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      ull h1=hs[i+r][j+c]-hs[i+r][j]*Mc;
      ull h2=hs[i][j+c]-hs[i][j]*Mc;
      ull hss=h1-h2*Mr;
      if( hss==ht) cout << i << " " << j << endl;
    }
  }
  
}
accuracy: 1
time_ms: 380
memory_kb: 14624
final_rank: 10

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;


struct slv{
  int h,w,r,c;
  vector<vector<ull>> hs;
  ull M1=1000000007;
  ull M2=998244353;
  ull ht,Mr,Mc;
  
  slv(vector<vector<char>> &s,vector<vector<char>> &t)
   :h(s.size()),w(s[0].size()),r(t.size()),c(t[0].size()),hs(h+1,vector<ull>(w+1,0)){

    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
      }
      for(int j=0;j<w;j++){
        hs[i+1][j+1]+=hs[i][j+1]*M2;
      }
    }
    ht=0;
    for(int i=0;i<r;i++){
      ull ht1=0;
      for(int j=0;j<c;j++){
        ht1=ht1*M1+t[i][j];
      }
      ht=ht*M2+ht1;
    }
    
    Mr=1,Mc=1;
    for(int i=0;i<r;i++) Mr*=M2;
    for(int j=0;j<c;j++) Mc*=M1;
  }
  
  ull get(int i,int j){
        return hs[i+r][j+c]-hs[i+r][j]*Mc+(hs[i][j]*Mc-hs[i][j+c])*Mr;
  }

};

int main(){
  int h,w,r,c;
  cin >> h >> w;
  vector s(h,vector<char>(w));
  for(int i=0;i<h;i++)for(int j=0;j<w;j++) cin >> s[i][j];
  cin >> r >> c;
  vector t(r,vector<char>(c));
  for(int i=0;i<r;i++)for(int j=0;j<c;j++) cin >> t[i][j];
  
  slv sv(s,t);
  ull ht=sv.ht;
    for(int i=0;i<=h-r;i++){
      for(int j=0;j<=w-c;j++){
        ull hss=sv.get(i,j);
        if( hss==ht) cout << i << " " << j << endl;
      }
    }
}
accuracy: 1
time_ms: 400
memory_kb: 12888
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

template <ull b1 = 9973, ull b2 = 1000000007>
struct rolling_hash2 {
    const int h, w;
    vector<ull> rh, rw;
    vector<vector<ull>> hs;
    template <class T> rolling_hash2(const vector<vector<T>>& a)
        : h(a.size()), w(a[0].size()), rh(h+1), rw(w+1), hs(h+1, vector<ull>(w+1))
    {
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                hs[i+1][j+1] = hs[i+1][j] * b2 + a[i][j];
            }
            for (int j = 0; j < w; ++j) {
                hs[i+1][j+1] += hs[i][j+1] * b1;
            }
        }
        rh[0] = rw[0] = 1;
        for (int i = 0; i < h; ++i) {
            rh[i+1] = rh[i] * b1;
        }
        for (int i = 0; i < w; ++i) {
            rw[i+1] = rw[i] * b2;
        }
    }
    ull get(int i1, int j1, int i2, int j2) {
        assert(0 <= i1 and i1 <= i2 and i2 <= h);
        assert(0 <= j1 and j1 <= j2 and j2 <= w);
        ull u = hs[i2][j2] - hs[i2][j1] * rw[j2 - j1];
        ull d = hs[i1][j2] - hs[i1][j1] * rw[j2 - j1];
        return u - d * rh[i2 - i1];
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int h,w; cin >> h >> w;
    vector<vector<char>> a(h, vector<char>(w));
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            cin >> a[i][j];
        }
    }
    int r,c; cin >> r >> c;
    vector<vector<char>> b(r, vector<char>(c));
    for (int i = 0; i < r; ++i) {
        for (int j = 0; j < c; ++j) {
            cin >> b[i][j];
        }
    }
    rolling_hash2 rha(a), rhb(b);
    ull hsh = rhb.get(0,0,r,c);
    for (int i = 0; i+r <= h; ++i) {
        for (int j = 0; j+c <= w; ++j) {
            if (rha.get(i,j,i+r,j+c) == hsh) {
                cout << i << " " << j << "\n";
            }
        }
    }
}
accuracy: 1
time_ms: 40
memory_kb: 20744
final_rank: 1

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;

ull M1=1000000007;
ull M2=998244353;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
  int h,w,r,c;
  cin >> h >> w;
  vector s(h,vector<char>(w));
  for(int i=0;i<h;i++)for(int j=0;j<w;j++) cin >> s[i][j];
  cin >> r >> c;
  vector t(r,vector<char>(c));
  for(int i=0;i<r;i++)for(int j=0;j<c;j++) cin >> t[i][j];
  
  vector hs(h+1,vector<ull>(w+1,0));
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
    }
    for(int j=0;j<w;j++){
      hs[i+1][j+1]+=hs[i][j+1]*M2;
    }
  }
  ull ht=0;
  for(int i=0;i<r;i++){
    ull ht1=0;
    for(int j=0;j<c;j++){
      ht1=ht1*M1+t[i][j];
    }
    ht=ht*M2+ht1;
  }
  
  ull Mr=1,Mc=1;
  for(int i=0;i<r;i++) Mr*=M2;
  for(int j=0;j<c;j++) Mc*=M1;
  
  for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      ull hss=hs[i+r][j+c]-hs[i+r][j]*Mc+(hs[i][j]*Mc-hs[i][j+c])*Mr;
      if( hss==ht) cout << i << " " << j << endl;
    }
  }
}
accuracy: 1
time_ms: 370
memory_kb: 13004
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;

ull M1=1000000007;
ull M2=998244353;

int main(){
  int h,w,r,c;
  cin >> h >> w;
  vector s(h,vector<char>(w));
  for(int i=0;i<h;i++)for(int j=0;j<w;j++) cin >> s[i][j];
  cin >> r >> c;
  vector t(r,vector<char>(c));
  for(int i=0;i<r;i++)for(int j=0;j<c;j++) cin >> t[i][j];
  
  vector hs(h+1,vector<ull>(w+1,0));
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
    }
    for(int j=0;j<w;j++){
      hs[i+1][j+1]+=hs[i][j+1]*M2;
    }
  }
  ull ht=0;
  for(int i=0;i<r;i++){
    ull ht1=0;
    for(int j=0;j<c;j++){
      ht1=ht1*M1+t[i][j];
    }
    ht=ht*M2+ht1;
  }
  
  ull Mr=1,Mc=1;
  for(int i=0;i<r;i++) Mr*=M2;
  for(int j=0;j<c;j++) Mc*=M1;
  
  for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      ull hss=hs[i+r][j+c]-hs[i+r][j]*Mc+(hs[i][j]*Mc-hs[i][j+c])*Mr;
      if( hss==ht) cout << i << " " << j << endl;
    }
  }
}
accuracy: 1
time_ms: 390
memory_kb: 12812
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;
using ull=unsigned int64_t;

ull M1=1000000007;
ull M2=998244353;

int main(){
  int h,w,r,c;
  cin >> h >> w;
  vector<string> s(h);
  for(int i=0;i<h;i++) cin >> s[i];
  cin >> r >> c;
  vector<string> t(r);
  for(int i=0;i<r;i++) cin >> t[i];
  
  vector hs(h+1,vector<ull>(w+1,0));
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      hs[i+1][j+1]=hs[i+1][j]*M1+s[i][j];
    }
    for(int j=0;j<w;j++){
      hs[i+1][j+1]+=hs[i][j+1]*M2;
    }
  }
  ull ht=0;
  for(int i=0;i<r;i++){
    ull ht1=0;
    for(int j=0;j<c;j++){
      ht1=ht1*M1+t[i][j];
    }
    ht=ht*M2+ht1;
  }
  
  ull Mr=1,Mc=1;
  for(int i=0;i<r;i++) Mr*=M2;
  for(int j=0;j<c;j++) Mc*=M1;
  
  for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      ull hss=hs[i+r][j+c]-hs[i+r][j]*Mc-hs[i][j+c]*Mr+hs[i][j]*Mr*Mc;
      if( hss==ht) cout << i << " " << j << endl;
    }
  }
  
}
accuracy: 1
time_ms: 380
memory_kb: 14544
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=int64_t;

class RollingHash{
    private:
    ll B[5]={114514,1919,810,893,364364};
    ll C[5]={31415,9265,3589,79323,846};
    ll M[5]={1000000007,1000000009,999999937,998244353,2147483647};
    ll Binv[5],Cinv[5];
    
    public:
    vector<string> S;
    vector<vector<ll>> H[5],Hsum[5];
    
    //繰り返し二乗法
    ll BE(long long b,int e,int m){
        ll r=1;
        while(e){
            if(e&1){
                r=(r*b)%M[m];
            }
            b=(b*b)%M[m];
            e >>=1;
        }
        return r;
    }

    
    void init(vector<string> cs,int Mcount){ //Mcountは最大５重化まで
        S=cs;
        int n=S.size();
        int m;
        if(n==0){
            m=0;
        }else{
            m=S[0].size();
        }

        //逆元
        for(int i=0;i<Mcount;i++){
            Binv[i]=BE(B[i],M[i]-2,i);
            Cinv[i]=BE(C[i],M[i]-2,i);
        }
        
        //本体
        for(int i=0;i<Mcount;i++){
            H[i].resize(n+1);
            for(int j=0;j<n+1;j++){
                H[i][j].assign(m+1,{0});
            }
            ll b=1,c=1;
            for(int j=n-1;j>=0;j--){
                c=1;
                for(int k=m-1;k>=0;k--){
                    H[i][j][k]=(((b*c)%M[i])*(ll)S[j][k])%M[i];
                    c=(c*C[i])%M[i];
                }
                b=(b*B[i])%M[i];
            }
        }
        
        //累積和
        for(int i=0;i<Mcount;i++){
            Hsum[i].resize(n+1);
            for(int j=0;j<n+1;j++){
                Hsum[i][j].assign(m+1,{0});
            }
            for(int j=0;j<n;j++){
                for(int k=0;k<m;k++){
                    Hsum[i][j+1][k+1]=(Hsum[i][j+1][k+1]+H[i][j][k])%M[i];
                    Hsum[i][j+1][k+1]=(Hsum[i][j+1][k+1]+Hsum[i][j+1][k])%M[i];
                    Hsum[i][j+1][k+1]=(Hsum[i][j+1][k+1]+Hsum[i][j][k+1])%M[i];
                    Hsum[i][j+1][k+1]=(Hsum[i][j+1][k+1]-Hsum[i][j][k]+M[i])%M[i];
                }
            }
        }
    }
    
    //計算
    ll get(int l1,int r1,int l2,int r2,int i){
       ll R=(Hsum[i][l2+1][r2+1]-Hsum[i][l1][r2+1]-Hsum[i][l2+1][r1]+Hsum[i][l1][r1])%M[i];
        R=(R+M[i])%M[i];
        R=(R*BE(Binv[i],(S.size())-l2-1,i))%M[i];
        R=(R*BE(Cinv[i],(S[0].size())-r2-1,i))%M[i];
        return R;
    }
  
};

int main(){
  
  int h,w,r,c;
  cin >> h >> w;
  vector<string> s(h);
  for(int i=0;i<h;i++) cin >> s[i];
  cin >> r >> c;
  vector<string> t(r);
  for(int i=0;i<r;i++) cin >> t[i];
  
  RollingHash rsh;
  rsh.init(s,2);
  RollingHash rth;
  rth.init(t,2);
  ll thash1=rth.get(0,0,r-1,c-1,0),thash2=rth.get(0,0,r-1,c-1,1);
  ll shash1=0,shash2=0;
 for(int i=0;i<=h-r;i++){
    for(int j=0;j<=w-c;j++){
      shash1=rsh.get(i,j,i+r-1,j+c-1,0);
      shash2=rsh.get(i,j,i+r-1,j+c-1,1);
      if((thash1==shash1)&&(thash2==shash2)) cout << i << " " << j << endl; 
    }
  }
  
}
accuracy: 1
time_ms: 710
memory_kb: 72728
final_rank: 18