首页 > 试题广场 >

可匹配子段计数

[编程题]可匹配子段计数
  • 热度指数:1554 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}给定整数数组 a(长度 n)与数组 b(长度 mm\leqq n)。设一个长度为 m 的数组 c 被称为 可匹配的,当且仅当将 c 的元素重新排列后,与数组 b 在对应位置上至少有 k 个元素相等。
\hspace{15pt}对于 a 中的每一个长度恰为 m 的连续子段,都可视为一个候选数组 c。求满足条件的子段数量。

【形式化解释】
\hspace{15pt}若子段 a_{l..l+m-1} 经重排可与 b 至少 k 个位置相等,则称该子段为"可匹配的"。等价地,设 cnt_x(S) 为元素 x 在序列 S 中出现次数,则子段 c 的"匹配度"为 \operatorname{match}(c)=\sum_{x} \min\bigl(cnt_x(c),\ cnt_x(b)\bigr),若 \operatorname{match}(c)\geqq k 则符合要求。

输入描述:
\hspace{15pt}第一行输入整数 t\left(1\leqq t\leqq 10^{4}\right)——测试用例组数。 
\hspace{15pt}每个测试用例:
{\hspace{23pt}}_\texttt{•}\,一行三个整数 n,m,k\left(1\leqq k\leqq m\leqq n\leqq 2\times10^{5}\right)
{\hspace{23pt}}_\texttt{•}\,一行 n 个整数 a_1\dots a_n\ \left(1\leqq a_i\leqq10^{6}\right)
{\hspace{23pt}}_\texttt{•}\,一行 m 个整数 b_1\dots b_m\ \left(1\leqq b_i\leqq10^{6}\right)
输入保证所有测试用例的 n 之和、m 之和均不超过 2\times10^{5}


输出描述:
\hspace{15pt}对每个测试用例输出一行整数,表示满足条件的子段数量。
示例1

输入

1
4 1 1
4 1 5 6
6

输出

1
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    const t = Number(await readline());

    for (let l = 0; l < t; l++) {
        const [n, m, k] = (await readline()).split(" ").map(Number);
        const listA = (await readline()).split(" ").map(Number);
        const listB = (await readline()).split(" ").map(Number);

        let map = new Map();
        for (let c of listB) {
            map.set(c, (map.get(c) || 0) + 1);
        }

        let i = 0;
        let j = 0;
        let cnt = 0;
        let countMap = new Map();
        while (j < m) {
            countMap.set(listA[j], (countMap.get(listA[j]) || 0) + 1);
            if (
                map.has(listA[j]) &&
                countMap.get(listA[j]) <= map.get(listA[j]) &&
                j < m
            ) {
                cnt++;
            }
            j++;
        }
        j--;

        let ans = 0;
        if (cnt >= k) {
            ans++;
            // console.log('0  ans', ans);
        }
        // console.log('initial i, j ', i, j);

        while (j < n) {
            i++;
            j++;
            const removedChar = listA[i - 1];
            countMap.set(removedChar, countMap.get(removedChar) - 1);
            if (
                map.has(removedChar) &&
                countMap.get(removedChar) + 1 <= map.get(removedChar)
            ) {
                cnt--;
            }
            const addedChar = listA[j];
            countMap.set(addedChar, (countMap.get(addedChar) || 0) + 1);
            if (
                map.has(addedChar) &&
                countMap.get(addedChar) - 1 < map.get(addedChar)
            ) {
                cnt++;
            }
            // console.log("i,j", i, j, new Map(countMap));
            if (cnt >= k && j < n) {
                ans++;
                // console.log("cnt, ans", cnt, ans);
                // console.log("i,j ", i, j);
            }
        }
        console.log(ans);
    }
})();


发表于 2025-09-29 17:30:33 回复(0)