题意

给你两个数组, AABB,长度分别为nnmm,然你求AA中长度为mm的子数组,这个子数组A1A_1,满足 (A1[1]+B[1])%k==(A1[m]+B[m])%k(A_1[1] + B[1]) \% k == \dots (A_1[m] + B[m]) \% k

问你有多少个这样的子数组

思路

我们可以把上面的等式拆解下

(A1[1]+B[1])%k==(A1[2]+B[2])%k (A_1[1] + B[1]) \% k == (A_1[2] + B[2]) \% k

...

(A1[m1]+B[m1])%k==(A1[m]+B[m])%k (A_1[m-1] + B[m-1]) \% k == (A_1[m] + B[m]) \% k

然后左右移项

(A1[2]A1[1])%k==(B[1]B[2])%k (A_1[2] - A_1[1]) \% k == (B[1] - B[2]) \% k

...

(A1[m]A1[m1])%k==(B[m1]B[m])%k (A_1[m] - A_1[m-1]) \% k == (B[m-1] - B[m]) \% k

那么求个差分数组,就可以用kmp来匹配了

但是要注意c++c++的异号求余,是让商尽量大,所以得

注意相减的取模,把相减的取模转换成正数

代码


/**
 *    author: andif
 *    created: 12.06.2023 22:50:58
**/
#include<bits/stdc++.h>
using namespace std;

#define de(x) cerr << #x << " = " << x << endl
#define dd(x) cerr << #x << " = " << x << " "
#define rep(i, a, b) for(int i = a; i < b; ++i)
#define per(i, a, b) for(int i = a; i > b; --i)
#define mt(a, b) memset(a, b, sizeof(a))
#define sz(a) (int)a.size()
#define fi first
#define se second
#define qc ios_base::sync_with_stdio(0);cin.tie(0)
#define eb emplace_back
#define all(a) a.begin(), a.end()
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;

vi get_next(const vi& a) {
    int n = sz(a) - 1;
    vi next(n + 1, 0);
    rep(i, 2, n + 1) {
        int j = i - 1;
        while(j && a[next[j] + 1] != a[i]) j = next[j];
        if (j) next[i] = next[j] + 1;
    }
    return next;
}

int match(const vi& a, const vi& b) {
    int n = sz(a) - 1, m = sz(b) - 1;
    vi next = get_next(b);
    int i = 1, j = 1;
    int ret = 0;
    while(i <= n) {
        if (a[i] == b[j]) {
            if (j == m) {
                ret++;
                j = next[j];
            }
            i++;
            j++;
        } else if (j == 1) {
            i++;
        } else {
            j = next[j - 1] + 1;
        }
    }
    return ret;
}

int main() {
    int t; cin >> t;
    while(t--) {
        int n, m, k; cin >> n >> m >> k;
        vi a(n + 1), b(m + 1);
        rep(i, 1, n + 1) cin >> a[i];
        rep(i, 1, m + 1) cin >> b[i];
        vi da(n), db(m);
        rep(i, 1, n) da[i] = ((a[i + 1] - a[i]) % k + k) % k;
        rep(i, 1, m) {
            db[i] = ((b[i] - b[i + 1]) % k + k) % k;
            // db[i] = -db[i];
        }
        // rep(i, 1, n) dd(i), de(da[i]);
        // rep(i, 1, m) dd(i), de(db[i]);
        int ans = match(da, db);
        cout << ans << '\n';
    }
    return 0;
}