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

Solution in C# (judge verdict: Accepted)

using System;
using System.Text;

// arihon p333
namespace ALDS1_14_C
{
    class Program
    {
        static int H, W, R, C;
        static char[][] field, pattern;
        static ulong[,] hash, tmp;
        static StringBuilder sb = new StringBuilder();

        static void Main(string[] args)
        {
            var t = scan;
            H = t[0]; W = t[1];
            field = new char[H][];
            hash = new ulong[H,W];
            tmp = new ulong[H, W];

            for (int i = 0; i < H; i++)
            {
                field[i] = Console.ReadLine().ToCharArray();
            }

            t = scan;
            R = t[0]; C = t[1];
            pattern = new char[R][];

            for (int i = 0; i < R; i++)
            {
                pattern[i] = Console.ReadLine().ToCharArray();
            }

            solve();

            Console.Write(sb);
        }
        static void solve()
        {
            if (R > H || C > W) return;

            //??????????????????????????\???????±???????
            ulong HP;
            compute_hash(pattern, R, C);
            HP = hash[0, 0];

            //?????????????????\????????????????????????????¨????
            compute_hash(field, H, W);
            for (int i = 0; i + R <= H; i++)
            {
                for (int j = 0; j + C <= W; j++)
                {
                    if (HP == hash[i, j]) sb.AppendLine(i + " " + j);
                }
            }
        }

        //a??????R*C?????¨????????¢?????????????????\????¨????
        static void compute_hash(char[][] a, int n, int m)
        {
            const ulong B1 = 9973;
            const ulong B2 = 100000007;

            ulong t1 = 1; //B1???C???
            for (int j = 0; j < C; j++) t1 *= B1;

            //???????????????????????\???????¨????
            for (int i = 0; i < n; i++)
            {
                ulong e = 0;
                for (int j = 0; j < C; j++) e = e * B1 + a[i][j];

                for (int j = 0; j + C <= m; j++)
                {
                    tmp[i, j] = e;
                    if (j + C < m) e = e * B1 - t1 * a[i][j] + a[i][j + C];
                }
            }

            ulong t2 = 1; //B2??????
            for (int i = 0; i < R; i++) t2 *= B2;

            //???????????????????????\???????¨????
            for (int j = 0; j + C <= m ; j++)
            {
                ulong e = 0;
                for (int i = 0; i < R; i++) e = e * B2 + tmp[i, j];

                for (int i = 0; i + R <= n; i++)
                {
                    hash[i, j] = e;
                    if (i + R < n) e = e * B2 - t2 * tmp[i, j] + tmp[i + R, j];
                }
            }

        }
        static int[] scan { get { return Array.ConvertAll(Console.ReadLine().Split(), int.Parse); } }
    }
}