Problem:
Aerial Photos
Hideyo has come by two aerial photos of the same scale and orientation. You can see various types of buildings, but some areas are hidden by clouds. Apparently, they are of the same area, and the area covered by the second photograph falls entirely within the first. However, because they were taken at different time points, different shapes and distribution of clouds obscure identification where the area in the second photograph is located in the first. There may even be more than one area within the first that the second fits equally well.
A set of pixel information is given for each of the photographs. Write a program to extract candidate sub-areas within the first photograph that compare with the second equally well and output the number of the candidates.
Input
The input is given in the following format.
AW
AH
BW
BH
arow
1
arow
2
:
arow
AH
brow
1
brow
2
:
brow
BH
The first line provides the number of pixels in the horizontal and the vertical direction
AW
(1 ≤
AW
≤ 800) and
AH
(1 ≤
AH
≤ 800) for the first photograph, followed by those for the second
BW
(1 ≤
BW
≤ 100) and
BH
(1 ≤
BH
≤ 100) (
AW
≥
BW
and
AH
≥
BH
). Each of the subsequent
AH
lines provides pixel information (
arow
i
) of the
i
-th row from the top of the first photograph. Each of the
B
H lines that follows provides pixel information (
brow
i
) of the
i
-th row from the top of the second photograph.
Each of the pixel information
arow
i
and
brow
i
is a string of length
AW
and
BW
, respectively, consisting of upper/lower-case letters, numeric characters, or "
?
". Each one character represents a pixel, whereby upper/lower-case letters and numeric characters represent a type of building, and "
?
" indicates a cloud-covered area.
Output
Output the number of the candidates.
Sample Input 1
5 5 3 3
AF??z
W?p88
???Hk
pU?m?
F???c
F??
p?8
?H?
Sample Output 1
4
Sample Input 2
6 5 4 2
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaa
aaaa
Sample Output 2
12

Submitted solutions:

code_snippet: // AOJ #378
// Aerial Photo 2025.2.9

#include <iostream>
#include <vector>
#include <string>
#include <emmintrin.h>  // SSE2 ヘッダ
using namespace std;
using ll = long long;

static inline bool checkRowSSE(const char* a, const char* b, int len) {
    __m128i q = _mm_set1_epi8('?');
    int i = 0;
    for(; i <= len - 16; i += 16) {
        __m128i va = _mm_loadu_si128((const __m128i*)(a + i));
        __m128i vb = _mm_loadu_si128((const __m128i*)(b + i));
        __m128i cmpA = _mm_cmpeq_epi8(va, q);
        __m128i cmpB = _mm_cmpeq_epi8(vb, q);
        __m128i cmpEq = _mm_cmpeq_epi8(va, vb);
        __m128i valid = _mm_or_si128(cmpA, _mm_or_si128(cmpB, cmpEq));
        int mask = _mm_movemask_epi8(valid);
        if (mask != 0xFFFF)
            return false;
    }
    for(; i < len; i++) {
        char ca = a[i], cb = b[i];
        if(ca != '?' && cb != '?' && ca != cb)
            return false;
    }
    return true;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int AW, AH, BW, BH;
    cin >> AW >> AH >> BW >> BH;
    vector<string> A(AH), B(BH);
    for (int i = 0; i < AH; i++) cin >> A[i];
    for (int i = 0; i < BH; i++) cin >> B[i];
 
    ll ans = 0;
    for (int y = 0; y <= AH - BH; y++){
        for (int x = 0; x <= AW - BW; x++){
            bool valid = true;
            for (int i = 0; i < BH; i++){
                if(!checkRowSSE(A[y+i].c_str() + x, B[i].c_str(), BW)){
                    valid = false;
                    break;
                }
            }
            if(valid) ans++;
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 4164
final_rank: 8

code_snippet: #line 1 "test/aoj/0378.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/0378"
#include <iostream>

#line 2 "math/convolution.hpp"
#include <cassert>
#include <type_traits>
#include <vector>

#line 2 "math/modint.hpp"

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

#include <utility>

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast moduler by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {
    }

    // @return m
    unsigned int umod() const {
        return _m;
    }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1)
        // < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    for (long long a : {2, 7, 61}) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

#line 212 "math/modint.hpp"
#include <numeric>
#line 214 "math/modint.hpp"

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral =
    typename std::conditional<std::is_integral<T>::value ||
                                  is_signed_int128<T>::value ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_signed_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_signed<T>::value) ||
                                  is_signed_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value, make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned =
    typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

#line 299 "math/modint.hpp"

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

public:
    static constexpr int mod() {
        return m;
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {
    }
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) {
        _v = ((unsigned int)(v) % umod());
    }

    unsigned int val() const {
        return _v;
    }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) {
        return *this = *this * rhs.inv();
    }

    mint operator+() const {
        return *this;
    }
    mint operator-() const {
        return mint() - *this;
    }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

private:
    unsigned int _v;
    static constexpr unsigned int umod() {
        return m;
    }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id>
struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

public:
    static int mod() {
        return (int)(bt.umod());
    }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {
    }
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) {
        _v = ((unsigned int)(v) % mod());
    }

    unsigned int val() const {
        return _v;
    }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) {
        return *this = *this * rhs.inv();
    }

    mint operator+() const {
        return *this;
    }
    mint operator-() const {
        return mint() - *this;
    }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() {
        return bt.umod();
    }
};

template <int id>
internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

#line 599 "math/modint.hpp"
template <typename T, typename std::enable_if_t<internal::is_modint<T>::value,
                                                std::nullptr_t> = nullptr>
std::istream& operator>>(std::istream& is, T& v) {
    long long x;
    is >> x;
    v = x;
    return is;
}
template <typename T, typename std::enable_if_t<internal::is_modint<T>::value,
                                                std::nullptr_t> = nullptr>
std::ostream& operator<<(std::ostream& os, const T& v) {
    os << v.val();
    return os;
}
#line 7 "math/convolution.hpp"
namespace internal {

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = internal::bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[internal::bsf(~(unsigned int)(s))];
        }
    }
}

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = internal::bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) *
                    inow.val();
            }
            inow *= sum_ie[internal::bsf(~(unsigned int)(s))];
        }
    }
}

}  // namespace internal

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << internal::ceil_pow2(n + m - 1);
    a.resize(z);
    internal::butterfly(a);
    b.resize(z);
    internal::butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    internal::butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353, class T,
          std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}

std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        // B = 2^63, -B <= x, r(real value) < B
        // (x, x - M, x - 2M, or x - 3M) = r (mod 2B)
        // r = c1[i] (mod MOD1)
        // focus on MOD1
        // r = x, x - M', x - 2M', x - 3M' (M' = M % 2^64) (mod 2B)
        // r = x,
        //     x - M' + (0 or 2B),
        //     x - 2M' + (0, 2B or 4B),
        //     x - 3M' + (0, 2B, 4B or 6B) (without mod!)
        // (r - x) = 0, (0)
        //           - M' + (0 or 2B), (1)
        //           -2M' + (0 or 2B or 4B), (2)
        //           -3M' + (0 or 2B or 4B or 6B) (3) (mod MOD1)
        // we checked that
        //   ((1) mod MOD1) mod 5 = 2
        //   ((2) mod MOD1) mod 5 = 3
        //   ((3) mod MOD1) mod 5 = 4
        long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {
            0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}
#line 3 "string/wildcard_matching.hpp"
std::vector<bool> wildcard_matching(std::string s, std::string t) {
    int n = s.size(), m = t.size();
    assert(n >= m);
    std::vector<long long> a1(n), a2(n), a3(n);
    for (int i = 0; i < n; i++) {
        a1[i] = s[i] == '?' ? 0 : (long long)s[i];
        a2[i] = a1[i] * a1[i];
        a3[i] = a2[i] * a1[i];
    }
    std::vector<long long> b1(m), b2(m), b3(m);
    for (int i = 0; i < m; i++) {
        b1[i] = t[i] == '?' ? 0 : (long long)t[i];
        b2[i] = b1[i] * b1[i];
        b3[i] = b2[i] * b1[i];
    }
    auto f = [](const std::vector<long long> &a, std::vector<long long> &b) {
        std::reverse(b.begin(), b.end());
        std::vector<long long> c = convolution_ll(a, b);
        return std::vector<long long>(c.begin() + b.size() - 1, c.end());
    };
    std::vector<long long> c1 = f(a3, b1);
    std::vector<long long> c2 = f(a2, b2);
    std::vector<long long> c3 = f(a1, b3);
    std::vector<bool> ret(n - m + 1);
    for (int i = 0; i < n - m + 1; i++) {
        ret[i] = c1[i] - c2[i] * 2 + c3[i] == 0;
    }
    return ret;
}
#line 5 "test/aoj/0378.test.cpp"
int main() {
    int aw, ah, bw, bh;
    std::cin >> aw >> ah >> bw >> bh;
    std::string s, t;
    for (int i = 0; i < ah; i++) {
        std::string a;
        std::cin >> a;
        s += a;
    }
    for (int i = 0; i < bh; i++) {
        std::string b;
        std::cin >> b;
        t += b;
        if (i < bh - 1) t += std::string(aw - bw, '?');
    }
    std::vector<bool> ok = wildcard_matching(s, t);
    int ans = 0;
    for (int i = 0; i < ah - bh + 1; i++) {
        for (int j = 0; j < aw - bw + 1; j++) {
            ans += ok[i * aw + j];
        }
    }
    std::cout << ans << '\n';
}
accuracy: 1
time_ms: 640
memory_kb: 55584
final_rank: 12

code_snippet: #line 1 "test.cpp"
#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

#line 2 "wildcard_matching.hpp"

#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/fast_fourier_transform.hpp"



#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/polynomial.hpp"



#line 8 "/home/ecasdqina/cpcpp/libs/library_cpp/math/polynomial.hpp"

namespace cplib {
template<class T>
class polynomial: public std::vector<T> {
public:
	using std::vector<T>::vector;
	using value_type = typename std::vector<T>::value_type;
	using reference = typename std::vector<T>::reference;
	using const_reference = typename std::vector<T>::const_reference;
	using size_type = typename std::vector<T>::size_type;

public:
	polynomial(const std::vector<T>& r): std::vector<T>(r) {}
	polynomial(size_t size, std::function<T(size_t)> f): std::vector<T>(size) {
		for(size_t i = 0; i < size; i++) (*this)[i] = f(i);
	}

	polynomial operator+(const polynomial& r) const { return polynomial(*this) += r; }
	polynomial operator+(const_reference r) const { return polynomial(*this) += r; }
	friend polynomial operator+(const_reference l, polynomial r) { return r += l; }
	polynomial operator-(const polynomial& r) const { return polynomial(*this) -= r; }
	polynomial operator-(const_reference r) const { return polynomial(*this) -= r; }
	friend polynomial operator-(const_reference l, polynomial r) { return r -= l; }
	polynomial operator*(const_reference r) const { return polynomial(*this) *= r; }
	friend polynomial operator*(const_reference l, polynomial r) { return r *= l; }
	polynomial operator*(const polynomial& r) const { return polynomial(*this) *= r; }
	polynomial operator/(const_reference r) const { return polynomial(*this) /= r; }
	polynomial operator<<(size_type r) const { return polynomial(*this) <<= r; }
	polynomial operator>>(size_type r) const { return polynomial(*this) >>= r; }
	polynomial operator-() const {
		polynomial ret(this->size());
		for(size_t i = 0; i < this->size(); i++) ret[i] = -(*this)[i];
		return ret;
	}
	polynomial& operator+=(const polynomial& r) {
		if(r.size() > this->size()) this->resize(r.size());
		for(size_t i = 0; i < r.size(); i++) (*this)[i] = (*this)[i] + r[i];
		return *this;
	}
	polynomial& operator+=(const_reference r) {
		if(this->empty()) this->push_back(T{});
		(*this)[0] += r;
		return *this;
	}
	polynomial& operator-=(const polynomial& r) {
		if(r.size() > this->size()) this->resize(r.size());
		for(size_t i = 0; i < r.size(); i++) (*this)[i] = (*this)[i] - r[i];
		return *this;
	}
	polynomial& operator-=(const_reference r) {
		if(this->empty()) this->push_back(T{});
		(*this)[0] -= r;
		return *this;
	}
	polynomial& operator*=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}
	polynomial& operator/=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] / r;
		return *this;
	}
	polynomial& operator<<=(size_type r) {
		this->insert(begin(*this), r, T{});
		return *this;
	}
	polynomial& operator>>=(size_type r) {
		if(r >= this->size()) this->clear();
		else this->erase(begin(*this), begin(*this) + r);
		return *this;
	}
	polynomial& operator*=(const polynomial& r) {
		polynomial ret(this->degree() + r.degree() + 1);
		for(size_t i = 0; i < this->size(); i++) {
			if((*this)[i] == T{}) continue;
			for(size_t j = 0; j < r.size(); j++) ret[i + j] += (*this)[i] * r[j];
		}
		return *this = std::move(ret);
	};

	polynomial differential(size_type k) const {
		polynomial ret(*this);
		for(size_t i = 0; i < k; i++) ret = ret.differential();
		return ret;
	}
	polynomial differential() const {
		if(degree() < 1) return polynomial();
		polynomial ret(this->size() - 1);
		for(size_t i = 1; i < this->size(); i++) ret[i - 1] = (*this)[i] * T(i);
		return ret;
	}
	polynomial integral(size_type k) const {
		polynomial ret(*this);
		for(size_t i = 0; i < k; i++) ret = ret.integral();
		return ret;
	}
	polynomial integral() const {
		polynomial ret(this->size() + 1);
		for(size_t i = 0; i < this->size(); i++) ret[i + 1] = (*this)[i] / T(i + 1);
		return ret;
	}
	polynomial prefix(size_type size) const {
		return polynomial(begin(*this), begin(*this) + std::min(this->size(), size));
	}
	void shrink() {
		while(!this->empty() and this->back() == T{}) this->pop_back();
	}

public:
	polynomial sparse_convex(const polynomial& r) const {
		if(this->nonzeros() < r.nonzeros()) return (*this) * r;
		return r * (*this);
	}
	size_type degree() const { return std::max<size_type>(1, this->size()) - 1; }
	size_type nonzeros() const {
		size_type ret = 0;
		for(size_t i = 0; i < this->size(); i++) {
			if((*this)[i] != T{}) ret++;
		}
		return ret;
	}
	T operator()(T x) const { return eval(x); }
	T eval(T x) const {
		T ret = (*this)[0], tmp = x;
		for(size_t i = 1; i < this->size(); i++) {
			ret = ret + (*this)[i] * tmp;
			tmp = tmp * x;
		}
		return ret;
	}

	static polynomial<T> one() { return term(0); }
	static polynomial<T> zero() { return polynomial<T>({T{0}}); }
	static polynomial<T> term(int k) { return polynomial<T>({T{1}}) << k; }
};

template<class T> T convex_all(std::vector<T> polies, int size = -1) {
	if(polies.empty()) return T::zero();

	std::deque<int> qu;
	for(int i = 0; i < polies.size(); i++) qu.push_back(i);
	while(qu.size() > 1) {
		int a = qu.front(); qu.pop_front();
		int b = qu.front(); qu.pop_front();

		polies.push_back(polies[a] * polies[b]);
		if(size != -1) polies.back().resize(size);
		qu.push_back((int)polies.size() - 1);
	}
	return polies.back();
}
}


#line 6 "/home/ecasdqina/cpcpp/libs/library_cpp/math/fast_fourier_transform.hpp"

namespace cplib {
template<class T, class Real = double, class Complex = std::complex<Real>>
class fast_fourier_transform: public polynomial<T> {
public:
	using polynomial<T>::polynomial;
	using value_type = typename polynomial<T>::value_type;
	using reference = typename polynomial<T>::reference;
	using const_reference = typename polynomial<T>::const_reference;
	using size_type = typename polynomial<T>::size_type;

private:
	// constexpr Real PI = std::numbers::pi_v<Real>;
	static constexpr Real PI = std::acos(Real(-1));;

	void transform(polynomial<Complex>& a, bool inverse = false) {
		size_type n = 0;
		while((1 << n) < a.size()) n++;
		size_type N = 1 << n;
		a.resize(N);

		size_type mask = N - 1;
		polynomial<Complex> tmp(N);
		for(int i = N >> 1; i >= 1; i >>= 1) {
			Real theta = 2 * PI * i * (inverse ? -1 : 1) / N;
			Complex zeta(std::cos(theta), std::sin(theta));
			Complex powZeta(1);

			for(int j = 0; j < N; j += i) {
				for(int k = 0; k < i; k++) {
					tmp[j + k] = a[((j << 1) & mask) | k] + powZeta * a[(((j << 1) | i) & mask) | k];
				}
				powZeta *= zeta;
			}
			a.swap(tmp);
		}

		if(n & 1) {
			std::swap(a, tmp);
			for(int i = 0; i < N; i++) a[i] = tmp[i];
		}
		if(inverse) for(int i = 0; i < N; i++) a[i] /= N;
	}
	fast_fourier_transform convolution(const fast_fourier_transform& ar, const fast_fourier_transform& br) {
		size_type size = ar.degree() + br.degree() + 1;
		polynomial<Complex> a(size);
		for(int i = 0; i < ar.size(); i++) a[i].real(ar[i]);
		for(int i = 0; i < br.size(); i++) a[i].imag(br[i]);
		transform(a, false);

		int N = a.size();
		polynomial<Complex> c(N);
		for(int i = 0; i < N; i++) {
			int j = (i == 0 ? 0 : N - i);
			c[i] = (a[i] + conj(a[j])) * (a[i] - conj(a[j])) * Complex(0, -.25);
		}
		transform(c, true);

		fast_fourier_transform ret(size);
		for(int i = 0; i < size; i++) ret[i] = round(c[i].real());
		return ret;

	}
public:
	fast_fourier_transform(const polynomial<T>& p): polynomial<T>(p) {}

	fast_fourier_transform operator*(const_reference r) const { return fast_fourier_transform(*this) *= r; }
	fast_fourier_transform& operator*=(const_reference r) {
		for(int i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}
	fast_fourier_transform operator*(const fast_fourier_transform& r) const { return fast_fourier_transform(*this) *= r; }
	fast_fourier_transform& operator*=(const fast_fourier_transform& r) {
		return (*this) = convolution((*this), r);
	}
};
}

// @docs docs/fast_fourier_transform.md


#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/number_theoritic_transform.hpp"



#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/modint.hpp"



#line 5 "/home/ecasdqina/cpcpp/libs/library_cpp/math/modint.hpp"

namespace cplib {
template <std::uint_fast64_t Modulus>
class modint {
	using u32 = std::uint_fast32_t;
	using u64 = std::uint_fast64_t;
	using i32 = std::int_fast32_t;
	using i64 = std::int_fast64_t;

	inline u64 apply(i64 x) { return (x < 0 ? x + Modulus : x); };

public:
	u64 a;
	static constexpr u64 mod = Modulus;

	constexpr modint(const i64& x = 0) noexcept: a(apply(x % (i64)Modulus)) {}

	constexpr modint operator+(const modint& rhs) const noexcept { return modint(*this) += rhs; }
	constexpr modint operator-(const modint& rhs) const noexcept { return modint(*this) -= rhs; }
	constexpr modint operator*(const modint& rhs) const noexcept { return modint(*this) *= rhs; }
	constexpr modint operator/(const modint& rhs) const noexcept { return modint(*this) /= rhs; }
	constexpr modint operator^(const u64& k) const noexcept { return modint(*this) ^= k; }
	constexpr modint operator^(const modint& k) const noexcept { return modint(*this) ^= k.value(); }
	constexpr modint operator-() const noexcept { return modint(Modulus - a); }
	constexpr modint operator++() noexcept { return (*this) = modint(*this) + 1; }
	constexpr modint operator--() noexcept { return (*this) = modint(*this) - 1; }
	const bool operator==(const modint& rhs) const noexcept { return a == rhs.a; };
	const bool operator!=(const modint& rhs) const noexcept { return a != rhs.a; };
	const bool operator<=(const modint& rhs) const noexcept { return a <= rhs.a; };
	const bool operator>=(const modint& rhs) const noexcept { return a >= rhs.a; };
	const bool operator<(const modint& rhs) const noexcept { return a < rhs.a; };
	const bool operator>(const modint& rhs) const noexcept { return a > rhs.a; };
	constexpr modint& operator+=(const modint& rhs) noexcept {
		a += rhs.a;
		if (a >= Modulus) a -= Modulus;
		return *this;
	}
	constexpr modint& operator-=(const modint& rhs) noexcept {
		if (a < rhs.a) a += Modulus;
		a -= rhs.a;
		return *this;
	}
	constexpr modint& operator*=(const modint& rhs) noexcept {
		a = a * rhs.a % Modulus;
		return *this;
	}
	constexpr modint& operator/=(modint rhs) noexcept {
		u64 exp = Modulus - 2;
		while (exp) {
			if (exp % 2) (*this) *= rhs;

			rhs *= rhs;
			exp /= 2;
		}
		return *this;
	}
	constexpr modint& operator^=(u64 k) noexcept {
		auto b = modint(1);
		while(k) {
			if(k & 1) b = b * (*this);
			(*this) *= (*this);
			k >>= 1;
		}
		return (*this) = b;
	}
	constexpr modint& operator=(const modint& rhs) noexcept {
		a = rhs.a;
		return (*this);
	}

	const modint inverse() const {
		return modint(1) / *this;
	}
	const modint power(i64 k) const {
		if(k < 0) return modint(*this).inverse() ^ (-k);
		return modint(*this) ^ k;
	}

	explicit operator bool() const { return a; }
	explicit operator u64() const { return a; }
	constexpr u64& value() noexcept { return a; }
	constexpr const u64& value() const noexcept { return a; }

	friend std::ostream& operator<<(std::ostream& os, const modint& p) {
		return os << p.a;
	}
	friend std::istream& operator>>(std::istream& is, modint& p) {
		u64 t;
		is >> t;
		p = modint(t);
		return is;
	}
};
}


#line 7 "/home/ecasdqina/cpcpp/libs/library_cpp/math/number_theoritic_transform.hpp"

namespace cplib {
template<std::uint_fast64_t MOD,
	int primitive_root = 3,
	class T = modint<MOD>>
class number_theoritic_transform: public polynomial<T> {
public:
	using polynomial<T>::polynomial;
	using value_type 	  = typename polynomial<T>::value_type;
	using reference 	  = typename polynomial<T>::reference;
	using const_reference = typename polynomial<T>::const_reference;
	using size_type 	  = typename polynomial<T>::size_type;

public:
	number_theoritic_transform(const polynomial<T>& p): polynomial<T>(p) {}

protected:
	static void ntt(number_theoritic_transform& a) {
		size_t N = a.size();
		static std::vector<T> dw;
		if(dw.size() < N) {
			int n = dw.size();
			dw.resize(N);
			for(size_t i = n; i < N; i++) dw[i] = -(T(primitive_root) ^ ((T::mod - 1) >> (i + 2)));
		}

		for(size_t m = N; m >>= 1;) {
			T w = 1;
			for(size_t s = 0, k = 0; s < N; s += 2 * m) {
				for(size_t i = s, j = s + m; i < s + m; i++, j++) {
					T x = a[i], y = a[j] * w;
					a[i] = x + y;
					a[j] = x - y;
				}
				w *= dw[__builtin_ctz(++k)];
			}
		}
	}
	static void intt(number_theoritic_transform& a) {
		size_t N = a.size();
		static std::vector<T> idw;
		if(idw.size() < N) {
			size_t n = idw.size();
			idw.resize(N);
			for(size_t i = n; i < N; i++) idw[i] = (-(T(primitive_root) ^ ((T::mod - 1) >> (i + 2)))).inverse();
		}

		for(size_t m = 1; m < N; m *= 2) {
			T w = 1;
			for(size_t s = 0, k = 0; s < N; s += 2 * m) {
				for(size_t i = s, j = s + m; i < s + m; i++, j++) {
					T x = a[i], y = a[j];
					a[i] = x + y;
					a[j] = (x - y) * w;
				}
				w *= idw[__builtin_ctz(++k)];
			}
		}
	}
	static void transform(number_theoritic_transform& a, bool inverse = false) {
		size_type n = 0;
		while((1ul << n) < a.size()) n++;
		size_type N = 1 << n;
		a.resize(N);

		if(!inverse) {
			ntt(a);
		} else {
			intt(a);
			T inv = T(N).inverse();
			for(size_t i = 0; i < a.size(); i++) a[i] *= inv;
		}
	}

	static number_theoritic_transform convolution(const number_theoritic_transform& ar, const number_theoritic_transform& br) {
		size_type size = ar.degree() + br.degree() + 1;
		number_theoritic_transform a(ar), b(br);
		a.resize(size);
		b.resize(size);

		transform(a, false);
		transform(b, false);

		for(size_t i = 0; i < a.size(); i++) a[i] *= b[i];
		transform(a, true);
		a.resize(size);
		return a;
	}

public:
	number_theoritic_transform convolute(const number_theoritic_transform& r) const { return (*this) * r; }
	number_theoritic_transform operator*(const number_theoritic_transform& r) const { return number_theoritic_transform(*this) *= r; }
	number_theoritic_transform& operator*=(const number_theoritic_transform& r) {
		return (*this) = convolution((*this), r);
	}
	number_theoritic_transform operator*(const_reference r) const { return number_theoritic_transform(*this) *= r; }
	number_theoritic_transform& operator*=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}

};
}
// @docs docs/number_theoritic_transform.md


#line 8 "wildcard_matching.hpp"

/*
# 注意
	計算時に用いる値の最大値は、文字の種類数 σ とマッチング文字列の長さ N について、2Nσ^2 となる。
	デフォルト実装では NTT<998244353> を用いているので、上記の値が 998244353 をこえるとバグる。
	対策: 大きい MOD を使う。FFT を使う。
*/

namespace cplib {
template<class convolution = number_theoritic_transform<998244353>> struct wildcard_matching_t {
	using value_type = typename convolution::value_type;
	using size_type = size_t;

	char wildcard = '?';

private:
	// "?abcde..." -> "012345..."
	constexpr std::vector<value_type> string_to_num_array(const std::string& s, char offset = 'a') const {
		std::vector<value_type> ret(s.size());
		for(size_t i = 0; i < s.size(); i++) {
			ret[i] = s[i] - offset + 1;
			if(s[i] == wildcard) ret[i] = 0;
		}
		return std::move(ret);
	}
	// "?abcde..." -> "011111..."
	constexpr std::vector<value_type> string_to_bin_array(const std::string& s) const {
		std::vector<value_type> ret(s.size(), 1);
		for(size_t i = 0; i < s.size(); i++) if(s[i] == wildcard) ret[i] = 0;
		return std::move(ret);
	}

public:
	// c_k = \sum_{i = 0}^{M - 1}a_{i + k}b_i
	constexpr std::vector<value_type> cross_correlation(std::vector<value_type> a, std::vector<value_type> b) const {
		reverse(begin(a), end(a));
		auto c = convolution{a}.convolute(b).prefix(a.size());
		c.erase(begin(c), begin(c) + (b.size() - 1));
		reverse(begin(c), end(c));
		return std::move(c);
	}

public:
	template<class T>
	constexpr std::vector<bool> matching(const std::vector<T>& a, const std::vector<T>& b) const {
		std::vector<value_type> c(a.size()), d(b.size());
		for(size_t i = 0; i < a.size(); i++) c[i] = (a[i] != 0);
		for(size_t i = 0; i < b.size(); i++) d[i] = (b[i] != 0);
		auto A(c); for(size_t i = 0; i < A.size(); i++) A[i] = c[i] * a[i] * a[i];
		auto B(c); for(size_t i = 0; i < B.size(); i++) B[i] = c[i] * a[i];
		auto C(d); for(size_t i = 0; i < C.size(); i++) C[i] = d[i] * b[i];
		auto D(d); for(size_t i = 0; i < D.size(); i++) D[i] = d[i] * b[i] * b[i];

		std::vector<bool> m(a.size() - b.size() + 1);
		auto X = cross_correlation(A, d);
		auto Y = cross_correlation(B, C);
		auto Z = cross_correlation(c, D);
		for(size_t i = 0; i < m.size(); i++) m[i] = (X[i] - Y[i] * 2 + Z[i] == 0);
		return std::move(m);
	}

	constexpr std::vector<bool> matching(const std::string& s, const std::string& p) const {
		assert(!s.empty());
		assert(!p.empty());
		return matching(string_to_num_array(s), string_to_num_array(p));
	}
	constexpr std::vector<size_t> matching_index(const std::string& s, const std::string& p) const {
		auto match = matching(std::move(s), std::move(p));
		std::vector<size_t> ret;
		for(size_t i = 0; i < match.size(); i++) if(match[i]) ret.push_back(i);
		return std::move(ret);
	}

	char get_wildcard() const { return wildcard; }
	void set_wildcard(const char c) { wildcard = c; }
};
constexpr wildcard_matching_t<> wildcard_matching = wildcard_matching_t<>();
}
#line 18 "test.cpp"

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int AW, AH, BW, BH;
  std::cin >> AW >> AH >> BW >> BH;
  std::vector<int> s(AH * AW), p(AW * (BH - 1) + BW, 0);

  const auto convert = [](const char c) -> int {
    if (c == '?') {
      return 0;
    } else if ('0' <= c && c <= '9') {
      return c - '0' + 1;
    } else if ('a' <= c && c <= 'z') {
      return c - 'a' + 10 + 1;
    } else {
      return c - 'A' + 10 + 26 + 1;
    }
  };

  for (int i = 0; i != AH; ++i) {
    for (int j = 0; j != AW; ++j) {
      char c;
      std::cin >> c;
      s[AW * i + j] = convert(c);
    }
  }

  for (int i = 0; i != BH; ++i) {
    for (int j = 0; j != BW; ++j) {
      char c;
      std::cin >> c;
      p[AW * i + j] = convert(c);
    }
  }

  const auto m = cplib::wildcard_matching.matching(s, p);

  int ans = 0;
  for (int i = 0; i + BH <= AH; ++i) {
    for (int j = 0; j + BW <= AW; ++j) {
      if (m[AW * i + j]) {
        ++ans;
      }
    }
  }

  std::cout << ans << "\n";

  return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 98540
final_rank: 10

code_snippet: #line 1 "test.cpp"
#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

#line 2 "wildcard_matching.hpp"

#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/fast_fourier_transform.hpp"



#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/polynomial.hpp"



#line 8 "/home/ecasdqina/cpcpp/libs/library_cpp/math/polynomial.hpp"

namespace cplib {
template<class T>
class polynomial: public std::vector<T> {
public:
	using std::vector<T>::vector;
	using value_type = typename std::vector<T>::value_type;
	using reference = typename std::vector<T>::reference;
	using const_reference = typename std::vector<T>::const_reference;
	using size_type = typename std::vector<T>::size_type;

public:
	polynomial(const std::vector<T>& r): std::vector<T>(r) {}
	polynomial(size_t size, std::function<T(size_t)> f): std::vector<T>(size) {
		for(size_t i = 0; i < size; i++) (*this)[i] = f(i);
	}

	polynomial operator+(const polynomial& r) const { return polynomial(*this) += r; }
	polynomial operator+(const_reference r) const { return polynomial(*this) += r; }
	friend polynomial operator+(const_reference l, polynomial r) { return r += l; }
	polynomial operator-(const polynomial& r) const { return polynomial(*this) -= r; }
	polynomial operator-(const_reference r) const { return polynomial(*this) -= r; }
	friend polynomial operator-(const_reference l, polynomial r) { return r -= l; }
	polynomial operator*(const_reference r) const { return polynomial(*this) *= r; }
	friend polynomial operator*(const_reference l, polynomial r) { return r *= l; }
	polynomial operator*(const polynomial& r) const { return polynomial(*this) *= r; }
	polynomial operator/(const_reference r) const { return polynomial(*this) /= r; }
	polynomial operator<<(size_type r) const { return polynomial(*this) <<= r; }
	polynomial operator>>(size_type r) const { return polynomial(*this) >>= r; }
	polynomial operator-() const {
		polynomial ret(this->size());
		for(size_t i = 0; i < this->size(); i++) ret[i] = -(*this)[i];
		return ret;
	}
	polynomial& operator+=(const polynomial& r) {
		if(r.size() > this->size()) this->resize(r.size());
		for(size_t i = 0; i < r.size(); i++) (*this)[i] = (*this)[i] + r[i];
		return *this;
	}
	polynomial& operator+=(const_reference r) {
		if(this->empty()) this->push_back(T{});
		(*this)[0] += r;
		return *this;
	}
	polynomial& operator-=(const polynomial& r) {
		if(r.size() > this->size()) this->resize(r.size());
		for(size_t i = 0; i < r.size(); i++) (*this)[i] = (*this)[i] - r[i];
		return *this;
	}
	polynomial& operator-=(const_reference r) {
		if(this->empty()) this->push_back(T{});
		(*this)[0] -= r;
		return *this;
	}
	polynomial& operator*=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}
	polynomial& operator/=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] / r;
		return *this;
	}
	polynomial& operator<<=(size_type r) {
		this->insert(begin(*this), r, T{});
		return *this;
	}
	polynomial& operator>>=(size_type r) {
		if(r >= this->size()) this->clear();
		else this->erase(begin(*this), begin(*this) + r);
		return *this;
	}
	polynomial& operator*=(const polynomial& r) {
		polynomial ret(this->degree() + r.degree() + 1);
		for(size_t i = 0; i < this->size(); i++) {
			if((*this)[i] == T{}) continue;
			for(size_t j = 0; j < r.size(); j++) ret[i + j] += (*this)[i] * r[j];
		}
		return *this = std::move(ret);
	};

	polynomial differential(size_type k) const {
		polynomial ret(*this);
		for(size_t i = 0; i < k; i++) ret = ret.differential();
		return ret;
	}
	polynomial differential() const {
		if(degree() < 1) return polynomial();
		polynomial ret(this->size() - 1);
		for(size_t i = 1; i < this->size(); i++) ret[i - 1] = (*this)[i] * T(i);
		return ret;
	}
	polynomial integral(size_type k) const {
		polynomial ret(*this);
		for(size_t i = 0; i < k; i++) ret = ret.integral();
		return ret;
	}
	polynomial integral() const {
		polynomial ret(this->size() + 1);
		for(size_t i = 0; i < this->size(); i++) ret[i + 1] = (*this)[i] / T(i + 1);
		return ret;
	}
	polynomial prefix(size_type size) const {
		return polynomial(begin(*this), begin(*this) + std::min(this->size(), size));
	}
	void shrink() {
		while(!this->empty() and this->back() == T{}) this->pop_back();
	}

public:
	polynomial sparse_convex(const polynomial& r) const {
		if(this->nonzeros() < r.nonzeros()) return (*this) * r;
		return r * (*this);
	}
	size_type degree() const { return std::max<size_type>(1, this->size()) - 1; }
	size_type nonzeros() const {
		size_type ret = 0;
		for(size_t i = 0; i < this->size(); i++) {
			if((*this)[i] != T{}) ret++;
		}
		return ret;
	}
	T operator()(T x) const { return eval(x); }
	T eval(T x) const {
		T ret = (*this)[0], tmp = x;
		for(size_t i = 1; i < this->size(); i++) {
			ret = ret + (*this)[i] * tmp;
			tmp = tmp * x;
		}
		return ret;
	}

	static polynomial<T> one() { return term(0); }
	static polynomial<T> zero() { return polynomial<T>({T{0}}); }
	static polynomial<T> term(int k) { return polynomial<T>({T{1}}) << k; }
};

template<class T> T convex_all(std::vector<T> polies, int size = -1) {
	if(polies.empty()) return T::zero();

	std::deque<int> qu;
	for(int i = 0; i < polies.size(); i++) qu.push_back(i);
	while(qu.size() > 1) {
		int a = qu.front(); qu.pop_front();
		int b = qu.front(); qu.pop_front();

		polies.push_back(polies[a] * polies[b]);
		if(size != -1) polies.back().resize(size);
		qu.push_back((int)polies.size() - 1);
	}
	return polies.back();
}
}


#line 6 "/home/ecasdqina/cpcpp/libs/library_cpp/math/fast_fourier_transform.hpp"

namespace cplib {
template<class T, class Real = double, class Complex = std::complex<Real>>
class fast_fourier_transform: public polynomial<T> {
public:
	using polynomial<T>::polynomial;
	using value_type = typename polynomial<T>::value_type;
	using reference = typename polynomial<T>::reference;
	using const_reference = typename polynomial<T>::const_reference;
	using size_type = typename polynomial<T>::size_type;

private:
	// constexpr Real PI = std::numbers::pi_v<Real>;
	static constexpr Real PI = std::acos(Real(-1));;

	void transform(polynomial<Complex>& a, bool inverse = false) {
		size_type n = 0;
		while((1 << n) < a.size()) n++;
		size_type N = 1 << n;
		a.resize(N);

		size_type mask = N - 1;
		polynomial<Complex> tmp(N);
		for(int i = N >> 1; i >= 1; i >>= 1) {
			Real theta = 2 * PI * i * (inverse ? -1 : 1) / N;
			Complex zeta(std::cos(theta), std::sin(theta));
			Complex powZeta(1);

			for(int j = 0; j < N; j += i) {
				for(int k = 0; k < i; k++) {
					tmp[j + k] = a[((j << 1) & mask) | k] + powZeta * a[(((j << 1) | i) & mask) | k];
				}
				powZeta *= zeta;
			}
			a.swap(tmp);
		}

		if(n & 1) {
			std::swap(a, tmp);
			for(int i = 0; i < N; i++) a[i] = tmp[i];
		}
		if(inverse) for(int i = 0; i < N; i++) a[i] /= N;
	}
	fast_fourier_transform convolution(const fast_fourier_transform& ar, const fast_fourier_transform& br) {
		size_type size = ar.degree() + br.degree() + 1;
		polynomial<Complex> a(size);
		for(int i = 0; i < ar.size(); i++) a[i].real(ar[i]);
		for(int i = 0; i < br.size(); i++) a[i].imag(br[i]);
		transform(a, false);

		int N = a.size();
		polynomial<Complex> c(N);
		for(int i = 0; i < N; i++) {
			int j = (i == 0 ? 0 : N - i);
			c[i] = (a[i] + conj(a[j])) * (a[i] - conj(a[j])) * Complex(0, -.25);
		}
		transform(c, true);

		fast_fourier_transform ret(size);
		for(int i = 0; i < size; i++) ret[i] = round(c[i].real());
		return ret;

	}
public:
	fast_fourier_transform(const polynomial<T>& p): polynomial<T>(p) {}

	fast_fourier_transform operator*(const_reference r) const { return fast_fourier_transform(*this) *= r; }
	fast_fourier_transform& operator*=(const_reference r) {
		for(int i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}
	fast_fourier_transform operator*(const fast_fourier_transform& r) const { return fast_fourier_transform(*this) *= r; }
	fast_fourier_transform& operator*=(const fast_fourier_transform& r) {
		return (*this) = convolution((*this), r);
	}
};
}

// @docs docs/fast_fourier_transform.md


#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/number_theoritic_transform.hpp"



#line 1 "/home/ecasdqina/cpcpp/libs/library_cpp/math/modint.hpp"



#line 5 "/home/ecasdqina/cpcpp/libs/library_cpp/math/modint.hpp"

namespace cplib {
template <std::uint_fast64_t Modulus>
class modint {
	using u32 = std::uint_fast32_t;
	using u64 = std::uint_fast64_t;
	using i32 = std::int_fast32_t;
	using i64 = std::int_fast64_t;

	inline u64 apply(i64 x) { return (x < 0 ? x + Modulus : x); };

public:
	u64 a;
	static constexpr u64 mod = Modulus;

	constexpr modint(const i64& x = 0) noexcept: a(apply(x % (i64)Modulus)) {}

	constexpr modint operator+(const modint& rhs) const noexcept { return modint(*this) += rhs; }
	constexpr modint operator-(const modint& rhs) const noexcept { return modint(*this) -= rhs; }
	constexpr modint operator*(const modint& rhs) const noexcept { return modint(*this) *= rhs; }
	constexpr modint operator/(const modint& rhs) const noexcept { return modint(*this) /= rhs; }
	constexpr modint operator^(const u64& k) const noexcept { return modint(*this) ^= k; }
	constexpr modint operator^(const modint& k) const noexcept { return modint(*this) ^= k.value(); }
	constexpr modint operator-() const noexcept { return modint(Modulus - a); }
	constexpr modint operator++() noexcept { return (*this) = modint(*this) + 1; }
	constexpr modint operator--() noexcept { return (*this) = modint(*this) - 1; }
	const bool operator==(const modint& rhs) const noexcept { return a == rhs.a; };
	const bool operator!=(const modint& rhs) const noexcept { return a != rhs.a; };
	const bool operator<=(const modint& rhs) const noexcept { return a <= rhs.a; };
	const bool operator>=(const modint& rhs) const noexcept { return a >= rhs.a; };
	const bool operator<(const modint& rhs) const noexcept { return a < rhs.a; };
	const bool operator>(const modint& rhs) const noexcept { return a > rhs.a; };
	constexpr modint& operator+=(const modint& rhs) noexcept {
		a += rhs.a;
		if (a >= Modulus) a -= Modulus;
		return *this;
	}
	constexpr modint& operator-=(const modint& rhs) noexcept {
		if (a < rhs.a) a += Modulus;
		a -= rhs.a;
		return *this;
	}
	constexpr modint& operator*=(const modint& rhs) noexcept {
		a = a * rhs.a % Modulus;
		return *this;
	}
	constexpr modint& operator/=(modint rhs) noexcept {
		u64 exp = Modulus - 2;
		while (exp) {
			if (exp % 2) (*this) *= rhs;

			rhs *= rhs;
			exp /= 2;
		}
		return *this;
	}
	constexpr modint& operator^=(u64 k) noexcept {
		auto b = modint(1);
		while(k) {
			if(k & 1) b = b * (*this);
			(*this) *= (*this);
			k >>= 1;
		}
		return (*this) = b;
	}
	constexpr modint& operator=(const modint& rhs) noexcept {
		a = rhs.a;
		return (*this);
	}

	const modint inverse() const {
		return modint(1) / *this;
	}
	const modint power(i64 k) const {
		if(k < 0) return modint(*this).inverse() ^ (-k);
		return modint(*this) ^ k;
	}

	explicit operator bool() const { return a; }
	explicit operator u64() const { return a; }
	constexpr u64& value() noexcept { return a; }
	constexpr const u64& value() const noexcept { return a; }

	friend std::ostream& operator<<(std::ostream& os, const modint& p) {
		return os << p.a;
	}
	friend std::istream& operator>>(std::istream& is, modint& p) {
		u64 t;
		is >> t;
		p = modint(t);
		return is;
	}
};
}


#line 7 "/home/ecasdqina/cpcpp/libs/library_cpp/math/number_theoritic_transform.hpp"

namespace cplib {
template<std::uint_fast64_t MOD,
	int primitive_root = 3,
	class T = modint<MOD>>
class number_theoritic_transform: public polynomial<T> {
public:
	using polynomial<T>::polynomial;
	using value_type 	  = typename polynomial<T>::value_type;
	using reference 	  = typename polynomial<T>::reference;
	using const_reference = typename polynomial<T>::const_reference;
	using size_type 	  = typename polynomial<T>::size_type;

public:
	number_theoritic_transform(const polynomial<T>& p): polynomial<T>(p) {}

protected:
	static void ntt(number_theoritic_transform& a) {
		size_t N = a.size();
		static std::vector<T> dw;
		if(dw.size() < N) {
			int n = dw.size();
			dw.resize(N);
			for(size_t i = n; i < N; i++) dw[i] = -(T(primitive_root) ^ ((T::mod - 1) >> (i + 2)));
		}

		for(size_t m = N; m >>= 1;) {
			T w = 1;
			for(size_t s = 0, k = 0; s < N; s += 2 * m) {
				for(size_t i = s, j = s + m; i < s + m; i++, j++) {
					T x = a[i], y = a[j] * w;
					a[i] = x + y;
					a[j] = x - y;
				}
				w *= dw[__builtin_ctz(++k)];
			}
		}
	}
	static void intt(number_theoritic_transform& a) {
		size_t N = a.size();
		static std::vector<T> idw;
		if(idw.size() < N) {
			size_t n = idw.size();
			idw.resize(N);
			for(size_t i = n; i < N; i++) idw[i] = (-(T(primitive_root) ^ ((T::mod - 1) >> (i + 2)))).inverse();
		}

		for(size_t m = 1; m < N; m *= 2) {
			T w = 1;
			for(size_t s = 0, k = 0; s < N; s += 2 * m) {
				for(size_t i = s, j = s + m; i < s + m; i++, j++) {
					T x = a[i], y = a[j];
					a[i] = x + y;
					a[j] = (x - y) * w;
				}
				w *= idw[__builtin_ctz(++k)];
			}
		}
	}
	static void transform(number_theoritic_transform& a, bool inverse = false) {
		size_type n = 0;
		while((1ul << n) < a.size()) n++;
		size_type N = 1 << n;
		a.resize(N);

		if(!inverse) {
			ntt(a);
		} else {
			intt(a);
			T inv = T(N).inverse();
			for(size_t i = 0; i < a.size(); i++) a[i] *= inv;
		}
	}

	static number_theoritic_transform convolution(const number_theoritic_transform& ar, const number_theoritic_transform& br) {
		size_type size = ar.degree() + br.degree() + 1;
		number_theoritic_transform a(ar), b(br);
		a.resize(size);
		b.resize(size);

		transform(a, false);
		transform(b, false);

		for(size_t i = 0; i < a.size(); i++) a[i] *= b[i];
		transform(a, true);
		a.resize(size);
		return a;
	}

public:
	number_theoritic_transform convolute(const number_theoritic_transform& r) const { return (*this) * r; }
	number_theoritic_transform operator*(const number_theoritic_transform& r) const { return number_theoritic_transform(*this) *= r; }
	number_theoritic_transform& operator*=(const number_theoritic_transform& r) {
		return (*this) = convolution((*this), r);
	}
	number_theoritic_transform operator*(const_reference r) const { return number_theoritic_transform(*this) *= r; }
	number_theoritic_transform& operator*=(const_reference r) {
		for(size_t i = 0; i < this->size(); i++) (*this)[i] = (*this)[i] * r;
		return *this;
	}

};
}
// @docs docs/number_theoritic_transform.md


#line 8 "wildcard_matching.hpp"

/*
# 注意
	計算時に用いる値の最大値は、文字の種類数 σ とマッチング文字列の長さ N について、4Nσ^2 となる。
	デフォルト実装では NTT<998244353> を用いているので、上記の値が 998244353 をこえるとバグる。
	対策: 大きい MOD を使う。FFT を使う。

# アルゴリズム
	文字列を数値列に変換しておく。ワイルドカードを 0 に、それ以外の文字は distinct な値に変換する。
	文字列 S, T がマッチしているかどうかは以下の式の値が 0 になるかどうかで分かる。
	\sum_{i = 1}^{|S|} s_i * t_i * (s_i - t_i)^2
*/

namespace cplib {
template<class convolution = number_theoritic_transform<998244353>> struct wildcard_matching_t {
	using value_type = typename convolution::value_type;
	using size_type = size_t;

	char wildcard = '?';

private:
	// "?abcde..." -> "012345..."
	constexpr std::vector<value_type> string_to_num_array(const std::string& s, char offset = 'a') const {
		std::vector<value_type> ret(s.size());
		for(size_t i = 0; i < s.size(); i++) {
			ret[i] = s[i] - offset + 1;
			if(s[i] == wildcard) ret[i] = 0;
		}
		return std::move(ret);
	}
	// "?abcde..." -> "011111..."
	constexpr std::vector<value_type> string_to_bin_array(const std::string& s) const {
		std::vector<value_type> ret(s.size(), 1);
		for(size_t i = 0; i < s.size(); i++) if(s[i] == wildcard) ret[i] = 0;
		return std::move(ret);
	}

public:
	// c_k = \sum_{i = 0}^{M - 1}a_{i + k}b_i
	constexpr std::vector<value_type> cross_correlation(std::vector<value_type> a, std::vector<value_type> b) const {
		reverse(begin(a), end(a));
		auto c = convolution{a}.convolute(b).prefix(a.size());
		c.erase(begin(c), begin(c) + (b.size() - 1));
		reverse(begin(c), end(c));
		return std::move(c);
	}

public:
	template<class T>
	constexpr std::vector<bool> matching(const std::vector<T>& a, const std::vector<T>& b) const {
		std::vector<value_type> c(a.size()), d(b.size());
		for(size_t i = 0; i < a.size(); i++) c[i] = (a[i] != 0);
		for(size_t i = 0; i < b.size(); i++) d[i] = (b[i] != 0);
		auto A(c); for(size_t i = 0; i < A.size(); i++) A[i] = c[i] * a[i] * a[i];
		auto B(c); for(size_t i = 0; i < B.size(); i++) B[i] = c[i] * a[i];
		auto C(d); for(size_t i = 0; i < C.size(); i++) C[i] = d[i] * b[i];
		auto D(d); for(size_t i = 0; i < D.size(); i++) D[i] = d[i] * b[i] * b[i];

		std::vector<bool> m(a.size() - b.size() + 1);
		auto X = cross_correlation(A, d);
		auto Y = cross_correlation(B, C);
		auto Z = cross_correlation(c, D);
		for(size_t i = 0; i < m.size(); i++) m[i] = (X[i] - Y[i] * 2 + Z[i] == 0);
		return std::move(m);
	}

	constexpr std::vector<bool> matching(const std::string& s, const std::string& p) const {
		assert(!s.empty());
		assert(!p.empty());
		return matching(string_to_num_array(s), string_to_num_array(p));
	}
	constexpr std::vector<size_t> matching_index(const std::string& s, const std::string& p) const {
		auto match = matching(std::move(s), std::move(p));
		std::vector<size_t> ret;
		for(size_t i = 0; i < match.size(); i++) if(match[i]) ret.push_back(i);
		return std::move(ret);
	}

	char get_wildcard() const { return wildcard; }
	void set_wildcard(const char c) { wildcard = c; }
};
constexpr wildcard_matching_t<> wildcard_matching = wildcard_matching_t<>();
}
#line 18 "test.cpp"

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int AW, AH, BW, BH;
  std::cin >> AW >> AH >> BW >> BH;
  std::vector<int> s(AH * AW), p(AW * (BH - 1) + BW, 0);

  const auto convert = [](const char c) -> int {
    if (c == '?') {
      return 0;
    } else if ('0' <= c && c <= '9') {
      return c - '0' + 1;
    } else if ('a' <= c && c <= 'z') {
      return c - 'a' + 10 + 1;
    } else {
      return c - 'A' + 10 + 26 + 1;
    }
  };

  for (int i = 0; i != AH; ++i) {
    for (int j = 0; j != AW; ++j) {
      char c;
      std::cin >> c;
      s[AW * i + j] = convert(c);
    }
  }

  for (int i = 0; i != BH; ++i) {
    for (int j = 0; j != BW; ++j) {
      char c;
      std::cin >> c;
      p[AW * i + j] = convert(c);
    }
  }

  const auto m = cplib::wildcard_matching.matching(s, p);

  int ans = 0;
  for (int i = 0; i + BH <= AH; ++i) {
    for (int j = 0; j + BW <= AW; ++j) {
      if (m[AW * i + j]) {
        ++ans;
      }
    }
  }

  std::cout << ans << "\n";

  return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 98584
final_rank: 11

code_snippet: #include<iostream>
#include<algorithm>

#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder



#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <type_traits>
#include <vector>

namespace atcoder {

namespace internal {

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[bsf(~(unsigned int)(s))];
        }
    }
}

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i <= cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) *
                    inow.val();
            }
            inow *= sum_ie[bsf(~(unsigned int)(s))];
        }
    }
}

}  // namespace internal

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << internal::ceil_pow2(n + m - 1);
    a.resize(z);
    internal::butterfly(a);
    b.resize(z);
    internal::butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    internal::butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353,
          class T,
          std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}

std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        // B = 2^63, -B <= x, r(real value) < B
        // (x, x - M, x - 2M, or x - 3M) = r (mod 2B)
        // r = c1[i] (mod MOD1)
        // focus on MOD1
        // r = x, x - M', x - 2M', x - 3M' (M' = M % 2^64) (mod 2B)
        // r = x,
        //     x - M' + (0 or 2B),
        //     x - 2M' + (0, 2B or 4B),
        //     x - 3M' + (0, 2B, 4B or 6B) (without mod!)
        // (r - x) = 0, (0)
        //           - M' + (0 or 2B), (1)
        //           -2M' + (0 or 2B or 4B), (2)
        //           -3M' + (0 or 2B or 4B or 6B) (3) (mod MOD1)
        // we checked that
        //   ((1) mod MOD1) mod 5 = 2
        //   ((2) mod MOD1) mod 5 = 3
        //   ((3) mod MOD1) mod 5 = 4
        long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {
            0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}

}  // namespace atcoder

using namespace std;
using namespace atcoder;
int AW,AH,BW,BH;
main()
{
	cin>>AW>>AH>>BW>>BH;
	vector<long long>a1(AW*AH),a2(AW*AH),a3(AW*AH);
	for(int i=0;i<AH;i++)
	{
		string A;
		cin>>A;
		for(int j=0;j<AW;j++)
		{
			a1[i*AW+j]=A[j]=='?'?0:A[j];
			a2[i*AW+j]=a1[i*AW+j]*a1[i*AW+j];
			a3[i*AW+j]=a1[i*AW+j]*a2[i*AW+j];
		}
	}
	int len=BH*AW-(AW-BW);
	vector<long long>b1(len),b2(len),b3(len);
	for(int i=0;i<BH;i++)
	{
		string B;
		cin>>B;
		for(int j=0;j<BW;j++)
		{
			b1[i*AW+j]=B[j]=='?'?0:B[j];
			b2[i*AW+j]=b1[i*AW+j]*b1[i*AW+j];
			b3[i*AW+j]=b1[i*AW+j]*b2[i*AW+j];
		}
	}
	reverse(b1.begin(),b1.end());
	reverse(b2.begin(),b2.end());
	reverse(b3.begin(),b3.end());
	vector<long long>c1=convolution_ll(a3,b1);
	vector<long long>c2=convolution_ll(a2,b2);
	vector<long long>c3=convolution_ll(a1,b3);
	int ans=0;
	for(int i=0;i+BH<=AH;i++)
	{
		for(int j=0;j<=AW-BW;j++)
		{
			long t=c1[len-1+i*AW+j]-2*c2[len-1+i*AW+j]+c3[len-1+i*AW+j];
			if(t==0)ans++;
		}
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 940
memory_kb: 55128
final_rank: 14

code_snippet: #include <bitset>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
int transform(char ch) {
	if ('0' <= ch && ch <= '9') return ch - '0' + 1;
	if ('A' <= ch && ch <= 'Z') return ch - 'A' + 11;
	if ('a' <= ch && ch <= 'z') return ch - 'a' + 37;
	return 0;
}
bitset<640> bit1[128], bit2[128], bit3[128], bit4[128];
int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	int AH, AW, BH, BW;
	cin >> AW >> AH >> BW >> BH;
	vector<vector<int> > A(AH, vector<int>(AW)), B(BH, vector<int>(BW));
	for (int i = 0; i < AH; ++i) {
		string str;
		cin >> str;
		for (int j = 0; j < AW; ++j) {
			A[i][j] = transform(str[j]);
		}
	}
	for (int i = 0; i < BH; ++i) {
		string str;
		cin >> str;
		for (int j = 0; j < BW; ++j) {
			B[i][j] = transform(str[j]);
		}
	}
	for (int i = 0; i < BH; ++i) {
		for (int j = 0; j < BW; ++j) {
			for (int k = 0; k < 6; ++k) {
				bit3[i][j * 6 + k] = ((B[i][j] >> k) & 1);
				bit4[i][j * 6 + k] = (B[i][j] != 0 ? 1 : 0);
			}
		}
	}
	int ans = 0;
	for (int i = 0; i <= AH - BH; ++i) {
		for (int j = 0; j < BH; ++j) {
			for (int k = 0; k < BW; ++k) {
				for (int l = 0; l < 6; ++l) {
					bit1[j][k * 6 + l] = ((A[i + j][k] >> l) & 1);
					bit2[j][k * 6 + l] = (A[i + j][k] != 0 ? 1 : 0);
				}
			}
		}
		for (int j = 0; j <= AW - BW; ++j) {
			bool ok = true;
			for (int k = 0; k < BH; ++k) {
				if (((bit1[k] ^ bit3[k]) & (bit2[k] & bit4[k])) != 0) {
					ok = false;
					break;
				}
			}
			if (ok) {
				++ans;
			}
			if (j != AW - BW) {
				for (int k = 0; k < BH; ++k) {
					bit1[k] >>= 6;
					bit2[k] >>= 6;
					for (int l = 0; l < 6; ++l) {
						bit1[k][BW * 6 - 6 + l] = ((A[i + k][j + BW] >> l) & 1);
						bit2[k][BW * 6 - 6 + l] = (A[i + k][j + BW] != 0 ? 1 : 0);
					}
				}
			}
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1380
memory_kb: 5440
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
int num(char c){
  if ('A' <= c && c <= 'Z'){
    return c - 'A';
  } else if ('a' <= c && c <= 'z'){
    return c - 'a' + 26;
  } else if ('0' <= c && c <= '9'){
    return c - '0' + 52;
  } else {
    return 62;
  }
}
int main(){
  int AW, AH, BW, BH;
  cin >> AW >> AH >> BW >> BH;
  vector<vector<char>> A(AH + 200, vector<char>(AW + 200, '#'));
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      cin >> A[i][j];
    }
  }
  vector<vector<char>> B(BH, vector<char>(BW));
  for (int i = 0; i < BH; i++){
    for (int j = 0; j < BW; j++){
      cin >> B[i][j];
    }
  }
  vector<vector<int>> id(AH + 200, vector<int>(AW + 200));
  for (int i = 0; i < AH + 200; i++){
    for (int j = 0; j < AW + 200; j++){
      id[i][j] = i * (AW + 200) + j;
    }
  }
  bitset<1000000> X(0);
  for (int i = 0; i < AH + 200; i++){
    for (int j = 0; j < AW + 200; j++){
      if (A[i][j] != '?'){
        X.set(id[i][j]);
      }
    }
  }
  vector<vector<int>> posA(63);
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      if (A[i][j] != '?'){
        posA[num(A[i][j])].push_back(id[i][j]);
      }
    }
  }
  vector<vector<int>> posB(63);
  for (int i = 0; i < BH; i++){
    for (int j = 0; j < BW; j++){
      if (B[i][j] != '?'){
        posB[num(B[i][j])].push_back(id[i][j]);
      }
    }
  }
  bitset<1000000> ans(0);
  for (int i = 0; i < 1000000; i++){
    ans.set(i);
  }
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      if (A[i][j] != '#' && A[i + BH - 1][j + BW - 1] != '#'){
        ans.reset(id[i][j]);
      }
    }
  }
  for (int i = 0; i < 62; i++){
    for (int j : posA[i]){
      X.reset(j);
    }
    for (int j : posB[i]){
      ans |= X >> j;
    }
    for (int j : posA[i]){
      X.set(j);
    }
  }
  int cnt = 0;
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      if (ans[id[i][j]] == 0){
        cnt++;
      }
    }
  }
  cout << cnt << endl;
}
accuracy: 1
time_ms: 340
memory_kb: 10420
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
int num(char c){
  if ('A' <= c && c <= 'Z'){
    return c - 'A';
  } else if ('a' <= c && c <= 'z'){
    return c - 'a' + 26;
  } else if ('0' <= c && c <= '9'){
    return c - '0' + 52;
  } else {
    return 62;
  }
}
int main(){
  int AW, AH, BW, BH;
  cin >> AW >> AH >> BW >> BH;
  vector<vector<char>> A(AH + 200, vector<char>(AW + 200, '#'));
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      cin >> A[i][j];
    }
  }
  vector<vector<char>> B(BH, vector<char>(BW));
  for (int i = 0; i < BH; i++){
    for (int j = 0; j < BW; j++){
      cin >> B[i][j];
    }
  }
  vector<vector<int>> id(AH + 200, vector<int>(AW + 200));
  for (int i = 0; i < AH + 200; i++){
    for (int j = 0; j < AW + 200; j++){
      id[i][j] = i * (AW + 200) + j;
    }
  }
  bitset<1000000> X(0);
  for (int i = 0; i < AH + 200; i++){
    for (int j = 0; j < AW + 200; j++){
      if (A[i][j] != '?'){
        X.set(id[i][j]);
      }
    }
  }
  vector<vector<int>> posA(63);
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      if (A[i][j] != '?'){
        posA[num(A[i][j])].push_back(id[i][j]);
      }
    }
  }
  vector<vector<int>> posB(63);
  for (int i = 0; i < BH; i++){
    for (int j = 0; j < BW; j++){
      if (B[i][j] != '?'){
        posB[num(B[i][j])].push_back(id[i][j]);
      }
    }
  }
  bitset<1000000> ans;
  for (int i = 0; i < 62; i++){
    for (int j : posA[i]){
      X.reset(j);
    }
    for (int j : posB[i]){
      ans |= X >> j;
    }
    for (int j : posA[i]){
      X.set(j);
    }
  }
  int cnt = 0;
  for (int i = 100; i < AH + 100; i++){
    for (int j = 100; j < AW + 100; j++){
      if (ans[id[i][j]] == 0){
        cnt++;
      }
    }
  }
  cout << cnt << endl;
}
accuracy: 0.5357142857142857
time_ms: 260
memory_kb: 8956
final_rank: 19

code_snippet: #include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder



#include <cassert>
#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast moduler by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        // _umul128(z, im, &x);
        x = 0;
        std::abort();
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    for (long long a : {2, 7, 61}) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <type_traits>
#include <vector>

namespace atcoder {

namespace internal {

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[bsf(~(unsigned int)(s))];
        }
    }
}

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) *
                    inow.val();
            }
            inow *= sum_ie[bsf(~(unsigned int)(s))];
        }
    }
}

}  // namespace internal

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << internal::ceil_pow2(n + m - 1);
    a.resize(z);
    internal::butterfly(a);
    b.resize(z);
    internal::butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    internal::butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353,
          class T,
          std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}

std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        // B = 2^63, -B <= x, r(real value) < B
        // (x, x - M, x - 2M, or x - 3M) = r (mod 2B)
        // r = c1[i] (mod MOD1)
        // focus on MOD1
        // r = x, x - M', x - 2M', x - 3M' (M' = M % 2^64) (mod 2B)
        // r = x,
        //     x - M' + (0 or 2B),
        //     x - 2M' + (0, 2B or 4B),
        //     x - 3M' + (0, 2B, 4B or 6B) (without mod!)
        // (r - x) = 0, (0)
        //           - M' + (0 or 2B), (1)
        //           -2M' + (0 or 2B or 4B), (2)
        //           -3M' + (0 or 2B or 4B or 6B) (3) (mod MOD1)
        // we checked that
        //   ((1) mod MOD1) mod 5 = 2
        //   ((2) mod MOD1) mod 5 = 3
        //   ((3) mod MOD1) mod 5 = 4
        long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {
            0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}

}  // namespace atcoder


#include <algorithm>
#include <cassert>
#include <cstddef>
#include <vector>

std::vector<bool> wildcard_pattern_matching(const std::vector<int> &p,
                                            const std::vector<int> &s) {
  using ll = long long;
  using usize = std::size_t;
  static constexpr int mod = 1811939329;
  using mint = atcoder::static_modint<mod>;

  const usize n = p.size();
  const usize m = s.size();

  assert(1 <= n);
  assert(m <= m);
  assert(n + m - 1 <= (mod - 1 & ~(mod - 1) + 1));
  assert(std::all_of(p.begin(), p.end(), [](int x) { return -1 <= x < mod; }));
  assert(std::all_of(s.begin(), s.end(), [](int x) { return -1 <= x < mod; }));
  {
    const int max = std::max(*std::max_element(p.begin(), p.end()),
                             *std::max_element(s.begin(), s.end()));
    assert(ll(max) * max < mod);
    assert(ll(max) * max * p.size() < mod);
  }

  std::vector<mint> sum(m - n + 1, mint(0));

  const auto add = [&](const auto f, const auto g) {
    std::vector<mint> x(n), y(m);
    for (usize i = 0; i != n; ++i) {
      x[i] = f(p[n - 1 - i]);
    }
    for (usize i = 0; i != m; ++i) {
      y[i] = g(s[i]);
    }
    const auto z = atcoder::convolution(x, y);
    for (usize i = 0; i != m - n + 1; ++i) {
      sum[i] += z[n - 1 + i];
    }
  };

  add([](const int v) { return ll(v != -1) * v * v; },
      [](const int v) { return int(v != -1); });
  add([](const int v) { return -2 * int(v != -1) * v; },
      [](const int v) { return int(v != -1) * v; });
  add([](const int v) { return int(v != -1); },
      [](const int v) { return ll(v != -1) * v * v; });

  std::vector<bool> res(m - n + 1);
  for (usize i = 0; i != m - n + 1; ++i) {
    res[i] = sum[i].val() == 0;
  }

  return res;
}

#include <iostream>
#include <string>

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int AW, AH, BW, BH;
  std::cin >> AW >> AH >> BW >> BH;
  std::vector<int> s(AH * AW), p(AW * (BH - 1) + BW, -1);

  const auto convert = [](const char c) -> int {
    if (c == '?') {
      return -1;
    } else if ('0' <= c && c <= '9') {
      return c - '0';
    } else if ('a' <= c && c <= 'z') {
      return c - 'a' + 10;
    } else {
      return c - 'A' + 10 + 26;
    }
  };

  for (int i = 0; i != AH; ++i) {
    for (int j = 0; j != AW; ++j) {
      char c;
      std::cin >> c;
      s[AW * i + j] = convert(c);
    }
  }

  for (int i = 0; i != BH; ++i) {
    for (int j = 0; j != BW; ++j) {
      char c;
      std::cin >> c;
      p[AW * i + j] = convert(c);
    }
  }

  const auto m = wildcard_pattern_matching(p, s);
  int ans = 0;
  for (int i = 0; i + BH <= AH; ++i) {
    for (int j = 0; j + BW <= AW; ++j) {
      if (m[AW * i + j]) {
        ++ans;
      }
    }
  }

  std::cout << ans << "\n";

  return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 22408
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template <class T, class U>
vector<T> make_v(U size, const T& init){ return vector<T>(static_cast<size_t>(size), init); }

template<class... Ts, class U>
auto make_v(U size, Ts... rest) { return vector<decltype(make_v(rest...))>(static_cast<size_t>(size), make_v(rest...)); }

template<class T> void chmin(T &a, const T &b){ a = (a < b ? a : b); }
template<class T> void chmax(T &a, const T &b){ a = (a > b ? a : b); }


int main() {
    using bset = bitset<800>;
    int W, H, w, h;
    cin >> W >> H >> w >> h;
    vector<string> A(H), B(h);
    for (auto &&i : A) cin >> i;
    for (auto &&i : B) cin >> i;
    auto p = make_v(H, W-w+1, bset()), q = p;
    auto r = make_v(h, bset()), s = make_v(h, bset());
    for (int i = 0; i < H; ++i) {
        for (int j = 0; j+w-1 < W; ++j) {
            for (int k = 0; k < w; ++k) {
                if(A[i][j+k] == '?') {
                    for (int l = k<<3; l < (k+1)<<3; ++l) {
                        q[i][j].set(l);
                    }
                }else {
                    for (int l = 0; l < 8; ++l) {
                        if(A[i][j+k]&(1 << l)) p[i][j].set((k<<3)|l), q[i][j].set((k<<3)|l);
                    }
                }
            }
        }
    }
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            if(B[i][j] == '?') {
                for (int l = j<<3; l < (j+1)<<3; ++l) {
                    s[i].set(l);
                }
            }else {
                for (int l = 0; l < 8; ++l) {
                    if(B[i][j]&(1 << l)) r[i].set((j<<3)|l), s[i].set((j<<3)|l);
                }
            }
        }
    }
    int ans = 0;
    for (int i = 0; i+h-1 < H; ++i) {
        for (int j = 0; j+w-1 < W; ++j) {
            int ok = 1;
            for (int k = 0; k < h && ok; ++k) {
                ok &= ((p[i+k][j]&s[k]) == p[i+k][j]) & ((q[i+k][j]&r[k]) == r[k]);
            }
            if(ok) {
                ans++;
            }
        }
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 1570
memory_kb: 132224
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 64

char A[800][801];
char B[100][101];

int AW,AH,BW,BH;
int state_len;

ll MASK[100][3][256]; //MASK[パターンの行][列/64][文字]
ll state_table[100][3]; //状態配列
ll POW[NUM];
ll AMARI,NUMBER;


void makeMask(){

	for(int row = 0; row < BH; row++){
		for(int col = 0; col < 3; col++){
			for(int i = 0; i < 256; i++)MASK[row][col][i] = 0;
		}
	}

	AMARI = (ll)(BW%NUM);

	if(AMARI == 0){
		state_len = BW/NUM;
	}else{
		state_len = BW/NUM+1;
	}

	NUMBER = (1LL << (AMARI+(NUM-1))%NUM);

  	string L = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?";

	for(int B_row = 0; B_row < BH; B_row++){ //パターンの行
		for(int col = 0; col < L.size(); col++){ //文字等
			for(int i = 0; i < state_len; i++){
				for(int k = 0; k < NUM; k++){
					if(i*NUM+k >= BW)continue;
					if(B[B_row][i*NUM+k] == L[col] || L[col] == '?' || B[B_row][i*NUM+k] == '?'){
						MASK[B_row][i][L[col]] += POW[k]; //対象文字等との一致可能性をbitで表す
					}
				}
			}
		}
	}
}


int main(){

	for(int i = 0; i < NUM; i++)POW[i] = pow(2,i);

	scanf("%d %d %d %d",&AW,&AH,&BW,&BH);

	for(int row = 0; row < AH; row++){
		scanf("%s",A[row]);
	}

	for(int row = 0; row < BH; row++){
		scanf("%s",B[row]);
	}

	makeMask();

	int ans = 0,match_num,tmp;

	for(int A_row = 0; A_row+BH <= AH; A_row++){ //検索始点行

		for(int B_row = 0; B_row < BH; B_row++){
			for(int i= 0; i < state_len; i++){
				state_table[B_row][i] = 0; //状態配列を初期化
			}
		}

		for(int A_col = 0; A_col < AW; A_col++){ //検索始点列

			match_num = 0;

			for(int B_row = 0; B_row < BH; B_row++){ //縦にBH分比較

				for(int i = state_len-1; i >= 0; i--){ //デクリメント
					if(i == 0){
						tmp = 1; //最下位ビットは1
					}else{

						if(state_table[B_row][i-1] & POW[NUM-1]){ //★左に1ビットするので、新しい最下位ビットは、state_table[B_row][i-1]の最上位ビット★
							tmp = 1;
						}else{
							tmp = 0;
						}
					}

					state_table[B_row][i] = ((state_table[B_row][i] << 1)|tmp)&MASK[B_row][i][A[A_row+B_row][A_col]];
				}
				if(state_table[B_row][state_len-1]&NUMBER)match_num++; //最上位ビットが1なら、その行は一致
			}
			if(match_num == BH)ans++; //全部の行が一致した場合
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 4600
final_rank: 3

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

const auto CHARS = 64;
using Bit = bitset<800>;

int to_i(char c) {
  if(isdigit(c)) return c - '0';
  if(islower(c)) return c - 'a' + 10;
  if(isupper(c)) return c - 'A' + 36;
  return 63;
}

int main() {
  int AW, AH, BW, BH;
  cin >> AW >> AH >> BW >> BH;
  vector<string> a(AH), b(BH);
  for(auto v: {&a, &b}) for(auto& i: *v) cin >> i;

  vector<vector<int>> A(AH), B(BH);
  for(auto i = 0; i < AH; ++i) for(auto c: a[i]) A[i].emplace_back(to_i(c));
  for(auto i = 0; i < BH; ++i) for(auto c: b[i]) B[i].emplace_back(to_i(c));

  vector<vector<Bit>> T(CHARS, vector<Bit>(AH));
  for(auto i = 0; i < AH; ++i) for(auto j = 0; j < AW; ++j) {
    if(A[i][j] == to_i('?')) for(auto& k: T) k[i].set(j);
    else                     T[A[i][j]][i].set(j);
  }

  vector<Bit> ok(AH);
  for(auto& i: ok) i.set();
  for(auto i = 0; i < AH - BH + 1; ++i) {
    for(auto y = 0; y < BH; ++y) for(auto x = 0; x < BW; ++x) {
      auto c = B[y][x];
      if(c == to_i('?')) continue;
      ok[i] &= T[c][i+y] >> x;
    }
  }

  auto res = 0;
  for(auto i = 0; i < AH - BH + 1; ++i) for(auto j = 0; j < AW - BW + 1; ++j) if(ok[i][j]) ++res;
  cout << res << endl;
}
accuracy: 1
time_ms: 190
memory_kb: 12380
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define dbg(...) do{cerr<<__LINE__<<": ";dbgprint(#__VA_ARGS__, __VA_ARGS__);}while(0);

using namespace std;

namespace std{template<class S,class T>struct hash<pair<S,T>>{size_t operator()(const pair<S,T>&p)const{return ((size_t)1e9+7)*hash<S>()(p.first)+hash<T>()(p.second);}};template<class T>struct hash<vector<T>>{size_t operator()(const vector<T> &v)const{size_t h=0;for(auto i : v)h=h*((size_t)1e9+7)+hash<T>()(i)+1;return h;}};}
template<class T>ostream& operator<<(ostream &os, const vector<T> &v){os<<"[ ";rep(i,v.size())os<<v[i]<<(i==v.size()-1?" ]":", ");return os;}template<class T>ostream& operator<<(ostream &os,const set<T> &v){os<<"{ "; for(const auto &i:v)os<<i<<", ";return os<<"}";}
template<class T,class U>ostream& operator<<(ostream &os,const map<T,U> &v){os<<"{";for(const auto &i:v)os<<" "<<i.first<<": "<<i.second<<",";return os<<"}";}template<class T,class U>ostream& operator<<(ostream &os,const pair<T,U> &p){return os<<"("<<p.first<<", "<<p.second<<")";}
void dbgprint(const string &fmt){cerr<<endl;}template<class H,class... T>void dbgprint(const string &fmt,const H &h,const T&... r){cerr<<fmt.substr(0,fmt.find(","))<<"= "<<h<<" ";dbgprint(fmt.substr(fmt.find(",")+1),r...);}
typedef unsigned long long ll;typedef vector<int> vi;typedef pair<int,int> pi;const int inf = (int)1e9;const double INF = 1e12, EPS = 1e-9;

int main(){
	cin.tie(0); cin.sync_with_stdio(0);
	int H, W, h, w;
	cin >> W >> H >> w >> h;
	vector<string> A(H), B(h);
	set<char> cs;
	
	rep(i, H){ cin >> A[i]; for(char c : A[i]) cs.insert(c); }
	rep(i, h){ cin >> B[i]; for(char c : B[i]) cs.insert(c); }
	cs.erase('?');
	
	vector<vector<bool>> ok(H, vector<bool>(W, 1));
	
	for(char c : cs){
		int any = 0;
		vector<vector<ll>> t(H, vector<ll>(W));
		rep(i, H) for(int j = W - 1; j >= 0; j--){
			if(j < W - 1) t[i][j] = t[i][j + 1] << 1;
			if(A[i][j] != c && A[i][j] != '?'){
				t[i][j] |= 1;
				any |= 1;
			}
		}
		
		vector<vector<ll>> u(h, vector<ll>(2));
		rep(i, h) rep(j, w) if(B[i][j] == c){
			u[i][j / 64] |= 1ull << j % 64;
			any |= 2;
		}
		if(any != 3) continue;
		
		rep(i, H - h + 1) rep(j, W - w + 1) if(ok[i][j]){
			rep(k, h){
				if(u[k][0] & t[i + k][j]) goto BAD;
				if(w > 64 && (u[k][1] & t[i + k][j + 64])) goto BAD;
			}
			continue;
			BAD:
			ok[i][j] = 0;
		}
	}
	
	int ans = 0;
	rep(i, H - h + 1) rep(j, W - w + 1) if(ok[i][j]) ans++;
	cout << ans << endl;
	
	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 8788
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

using bs = bitset< 800 >;
using ss = bitset< 100 >;


int main()
{
  int W, H, M, N;
  int mat[800][800], beet[100][100];

  auto to = [&](char c)
  {
    if(islower(c)) return (c - 'a' + 10);
    if(isupper(c)) return (c - 'A' + 36);
    if(isdigit(c)) return (c - '0' + 0);
    return (~0);
  };


  cin >> W >> H >> M >> N;
  for(int i = 0; i < H; i++) {
    string s;
    cin >> s;
    for(int j = 0; j < W; j++) {
      mat[i][j] = to(s[j]);
    }
  }

  for(int i = 0; i < N; i++) {
    string s;
    cin >> s;
    for(int j = 0; j < M; j++) {
      beet[i][j] = to(s[j]);
    }
  }

  ss mask = 1;
  mask <<= M - 1;

  auto matching = [&](vector< int > &latte, vector< int > &malta)
  {
    bs ret;
    int tail = 0;
    ss bit1[62], bit2;
    for(int i = 0; i < malta.size(); i++) {
      if(malta[i] < 0) for(int j = 0; j < 62; j++) bit1[j][i] = true;
      else bit1[malta[i]][i] = true;
    }
    for(int i = 0; i < W; i++) {
      bit2 <<= 1;
      bit2 |= 1;
      if(~latte[i]) bit2 &= bit1[latte[i]];
      if((bit2 & mask).count()) ret[i] = true;
    }
    return (ret);
  };

  bs bits[800][100];
  for(int i = 0; i < H; i++) {
    for(int j = 0; j < N; j++) {
      vector< int > vec1(W), vec2(M);
      for(int k = 0; k < W; k++) vec1[k] = mat[i][k];
      for(int k = 0; k < M; k++) vec2[k] = beet[j][k];
      bits[i][j] = matching(vec1, vec2);
    }
  }

  int ret = 0;
  for(int i = 0; i <= H - N; i++) {
    for(int k = 0; k < W; k++) {
      bool flag = true;
      for(int j = 0; j < N; j++) {
        flag &= bits[i + j][j][k];
      }
      ret += flag;
    }
  }

  cout << ret << endl;
}
accuracy: 1
time_ms: 750
memory_kb: 13712
final_rank: 9

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

#define int long long

#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;

template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

typedef bitset<800>bs;
bs X;
int H,W,h,w;

int A[888][888];
int a[888][888];

bs latte[888];

bs malta[888][62];

int conv(char c){
   if(isupper(c))return c-'A';
   if(islower(c))return 26+c-'a';
   if(isdigit(c))return 52+c-'0';
   return -1;
}

signed main(){
    cin>>W>>H>>w>>h;

    rep(i,H){
        string s;cin>>s;
        rep(j,W)A[i][j]=conv(s[j]);
    }

    rep(i,h){
        string s;cin>>s;
        rep(j,w)a[i][j]=conv(s[j]);
    }

    rep(i,W)X[i]=1;

    rep(i,H)latte[i]=X;

    rep(i,H)rep(j,W)if(i+h>H||j+w>W)latte[i][j]=0;

    rep(i,H){
        rep(j,W){
            if(A[i][j]>=0)malta[i][A[i][j]][j]=1;
            else rep(k,62)malta[i][k][j]=1;
        }
    }

    for(int j=0;j<h;j++){
        for(int i=j;i<H;i++){
            for(int k=0;k<w;k++){
                if(a[j][k]>=0)latte[i-j]&=malta[i][a[j][k]]>>k;
            }
        }
    }

    int ans=0;
    rep(i,H)rep(j,W)ans+=latte[i][j];
    cout<<ans<<endl;
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 14240
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
 
int w1, w2, h1, h2, sum;
long long hash_a[800][800][10], hash_b[800][10];
long long cumo_a[800][800][10], cumo_b[800][10];
char s[800][700],t[800][800];
 
 
void make_table(){
  rep(i,h1) rep(j,w1-w2+1) {
    rep(k,w2){
      rep(l,6) hash_a[i][j][(k*6)/60] = hash_a[i][j][(k*6)/60]*2 + ( ((s[i][j+k]>>l)&1)?1:0);
      rep(l,6) cumo_a[i][j][(k*6)/60] = cumo_a[i][j][(k*6)/60]*2 + (s[i][j+k]==63?1:0);
    }
  }
  rep(i,h2) {
    rep(j,w2){
      rep(k,6) hash_b[i][(j*6)/60] = hash_b[i][(j*6)/60]*2 + (((t[i][j]>>k)&1)?1:0);
      rep(k,6) cumo_b[i][(j*6)/60] = cumo_b[i][(j*6)/60]*2 + (t[i][j]==63?1:0);
    }
  }
}
 
void count_s(){
  rep(i,h1-h2+1) {
    rep(j,w1-w2+1) {
      rep(k,h2) {
        int p1[10]={} ,p2[10]={} ;int flag = 0;
        rep(l,10){
          p1[l] = hash_a[i+k][j][l] ^ hash_b[k][l];
          p2[l] = cumo_a[i+k][j][l] | cumo_b[k][l];
          if( (p1[l] | p2[l]) != p2[l] ) { flag ++; break; }
        }
        if( flag ) break ;
        if( k == h2-1 ) sum++;
      }
    }
  }
}
 
void Za_a_tsu(){
  rep(i,h1)rep(j,w1){
    if('0'<=s[i][j]&&s[i][j]<='9')s[i][j]=(s[i][j]-'0');
    if('a'<=s[i][j]&&s[i][j]<='z')s[i][j]=(s[i][j]-'a'+11);
    if('A'<=s[i][j]&&s[i][j]<='Z')s[i][j]=(s[i][j]-'A'+37);
  }
  rep(i,h2)rep(j,w2){
    if('0'<=t[i][j]&&t[i][j]<='9')t[i][j]=(t[i][j]-'0');
    if('a'<=t[i][j]&&t[i][j]<='z')t[i][j]=(t[i][j]-'a'+11);
    if('A'<=t[i][j]&&t[i][j]<='Z')t[i][j]=(t[i][j]-'A'+37);
  }
}
 
signed main(){
  cin >> w1 >> h1 >> w2 >> h2;
  rep(i,h1) scanf("%s", s[i]);
  rep(i,h2) scanf("%s", t[i]);
  Za_a_tsu();
  make_table();
  count_s();
  cout << sum << endl;
}
accuracy: 0.32142857142857145
time_ms: 350
memory_kb: 75132
final_rank: 20

code_snippet: #include<iostream>
#include<cstdio>
#include<cassert>
using namespace std;
typedef unsigned long long ll;
static const int BIT = 64;
static const int TH_MAX = 800;
static const int TW_MAX = 800;
static const int PH_MAX = 100;
static const int PW_MAX = 100;

char T[TH_MAX][TW_MAX+1];
char P[PH_MAX][PW_MAX+1];

int PH, PW, TH, TW;
ll K, R, Y;

ll M[PH_MAX][PW_MAX/BIT+1][256];
ll st[PH_MAX][PW_MAX/BIT+1];

void makeMask(){
  R = PW%BIT;
  K = PW/BIT + (R>0?1:0);
  Y = (1LL<<(R + (BIT-1))%BIT);
  string L = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?";
  for ( int r = 0; r < PH; r++ ){
    for ( int c = 0; c < L.size(); c++ ){
      for ( int k = 0; k < K; k++ ){
        for ( int b = 0; b < BIT; b++ ){
          if ( k*BIT+b >= PW ) continue;
          if ( P[r][k*BIT+b] == L[c] || L[c] == '?' || P[r][k*BIT+b] == '?'){
            M[r][k][L[c]] += (1LL<<b);
          }
        }
      }
    }
  }
}

main(){
  cin >> TW >> TH >> PW >> PH;
  for ( int i = 0; i < TH; i++ ) scanf("%s", T[i]);
  for ( int i = 0; i < PH; i++ ) scanf("%s", P[i]);

  makeMask();

  int ans = 0;
  for ( int h = 0; h < TH; h++ ){
    for ( int i = 0; i < PH; i++ ){
      for ( int j = 0; j < K; j++ ) st[i][j] = 0;
    }
    for ( int w = 0; w < TW; w++ ){
      int ok = 0;
      for ( int r = 0; r < PH; r++){
        if ( h + r >= TH ) continue;

        for ( int k = K-1; k >= 0; k-- ){
          int ca = (st[r][k-1] & (1LL<<(BIT-1)))>0?1:0;
          if ( k == 0 ) ca = 1;
          st[r][k] = ((st[r][k] << 1) | ca ) & M[r][k][T[h+r][w]];
        }
        if ( st[r][K-1] & Y ) ok++;
      }
      if ( ok == PH ) ans++;
    }
  }

  cout << ans << endl;
}
accuracy: 1
time_ms: 330
memory_kb: 4212
final_rank: 4

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

int main() {
  int h,w,n,m;
  cin >> w >> h >> m >> n;
  string s[h],t[n];
  for(int i=0; i<h; i++) cin >> s[i];
  for(int i=0; i<n; i++) cin >> t[i];
  bitset<600> b[n][256];
  for(int i=0; i<n; i++) {
    for(int j=0; j<m; j++) {
      if(t[i][j]!='?') b[i][t[i][j]].set(j);
      else for(int k=0; k<256; k++) b[i][k].set(j);
    }
  }
  int ans=0;
  for(int i=0; i<h-n+1; i++) {
    bitset<600> r[n];
    for(int j=0; j<w; j++) {
      int cnt=0;
      for(int k=0; k<n; k++) {
        r[k]=(r[k]<<1).set(0);
        if(s[i+k][j]!='?') r[k]&=b[k][s[i+k][j]];
        if(r[k][m-1]) cnt++;
      }
      if(j>=m-1&&cnt==n) ans++;
    }
  }
  cout << ans << endl;
  return 0;
}
accuracy: 1
time_ms: 1230
memory_kb: 5828
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
vector<int> match(string &t,string &p) {
  //cout<<t<<" "<<p<<endl;
  using BS = bitset<100>;
  int n = t.length(), m = p.length();
  vector<BS> M(100);
  vector<int> res(n,0);
  for (int i=0;i<m;i++){
    if(p[i]=='?') for(int j=0;j<100;j++) M[j][i]=1;
    if(isdigit(p[i])) M[p[i]-'0'][i]=1;
    if(islower(p[i])) M[10+p[i]-'a'][i]=1;
    if(isupper(p[i])) M[36+p[i]-'A'][i]=1;
  }
  BS S(0);
  for (int i = 0; i < n; i++) {
    S=((S<<1)|BS(1));
    if(isdigit(t[i])) S&=M[t[i]-'0'];
    if(islower(t[i])) S&=M[10+t[i]-'a'];
    if(isupper(t[i])) S&=M[36+t[i]-'A'];
    
    if((S&(BS(1)<<(m-1))).count()) res[i]=1;
  }
  //for(int i=0;i<n;i++) cout<<res[i];cout<<endl;
  return res;
}

signed main(){
  int aw,ah,bw,bh;
  cin>>aw>>ah>>bw>>bh;
  string a[ah],b[bh];
  for(int i=0;i<ah;i++) cin>>a[i];
  for(int i=0;i<bh;i++) cin>>b[i];
  //for(int i=0;i<ah;i++) cout<<a[i]<<endl;;
  //for(int i=0;i<bh;i++) cout<<b[i]<<endl;;
  vector<int> G[ah][bh];
  for(int i=0;i<ah;i++)
    for(int j=0;j<bh;j++)
      G[i][j]=match(a[i],b[j]);
  
  int ans=0;
  for(int i=0;i<=ah-bh;i++){
    for(int j=0;j<aw;j++){
      int res=1;
      for(int k=0;k<bh;k++)
	res&=G[i+k][k][j];
      ans+=res;
    }
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 1490
memory_kb: 229096
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define int long long
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;

//??????TLE??§??? m(_)m

int w1,w2,h1,h2,sum;
int hash_a[800][800][10],hash_b[800][10];
int cumo_a[800][800][10],cumo_b[800][10];
char s[800][700],t[800][800];
 
 
void make_table(){
  rep(i,h1) rep(j,w1-w2+1) {
    rep(k,w2){
      rep(l,6)hash_a[i][j][(k*6)/60] = hash_a[i][j][(k*6)/60]*2+(((s[i][j+k]>>l)&1)?1:0);
      rep(l,6)cumo_a[i][j][(k*6)/60] = cumo_a[i][j][(k*6)/60]*2+(s[i][j+k]==63?1:0);
    }
  }
  rep(i,h2) {
    rep(j,w2){
      rep(k,6)hash_b[i][(j*6)/60] = hash_b[i][(j*6)/60]*2+(((t[i][j]>>k)&1)?1:0);
      rep(k,6)cumo_b[i][(j*6)/60] = cumo_b[i][(j*6)/60]*2+(t[i][j]==63?1:0);
    }
  }
}
 
void count_s(){
  rep(i,h1-h2+1) {
    rep(j,w1-w2+1) {
      rep(k,h2) {
        int p1[10]={} ,p2[10]={} ;int flag = 0;
        rep(l,10){
          p1[l] = hash_a[i+k][j][l] ^ hash_b[k][l];
          p2[l] = cumo_a[i+k][j][l] | cumo_b[k][l];
          if( (p1[l] | p2[l]) != p2[l] ) { flag ++; break; }
        }
        if( flag ) break ;
        if( k == h2-1 ) sum++;
      }
    }
  }
}
 
void Za_a_tsu(){
  rep(i,h1)rep(j,w1){
    if('0'<=s[i][j]&&s[i][j]<='9')s[i][j]=(s[i][j]-'0');
    if('a'<=s[i][j]&&s[i][j]<='z')s[i][j]=(s[i][j]-'a'+11);
    if('A'<=s[i][j]&&s[i][j]<='Z')s[i][j]=(s[i][j]-'A'+37);
  }
  rep(i,h2)rep(j,w2){
    if('0'<=t[i][j]&&t[i][j]<='9')t[i][j]=(t[i][j]-'0');
    if('a'<=t[i][j]&&t[i][j]<='z')t[i][j]=(t[i][j]-'a'+11);
    if('A'<=t[i][j]&&t[i][j]<='Z')t[i][j]=(t[i][j]-'A'+37);
  }
}
 
signed main(){
  cin >> w1 >> h1 >> w2 >> h2;
  rep(i,h1)scanf("%s",s[i]);
  rep(i,h2)scanf("%s",t[i]);
  Za_a_tsu();
  make_table();
  count_s();
  cout << sum << endl;
}
accuracy: 1
time_ms: 1120
memory_kb: 103696
final_rank: 16