HJ177 可匹配子段计数

知识点双指针

校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。

描述

给定整数数组 aa(长度 nn)与数组 bb(长度 mm,m≦nm≦n)。设一个长度为 mm 的数组 cc 被称为 可匹配的 ,当且仅当将 cc 的元素重新排列后,与数组 bb 在对应位置上至少有 kk 个元素相等。

对于 aa 中的每一个长度恰为 mm 的连续子段,都可视为一个候选数组 cc。求满足条件的子段数量。

【形式化解释】

若子段 al..l+m−1al..l+m−1​ 经重排可与 bb 至少 kk 个位置相等,则称该子段为"可匹配的"。等价地,设 cntx(S)cntx​(S) 为元素 xx 在序列 SS 中出现次数,则子段 cc 的"匹配度"为 match⁡(c)=∑xmin⁡(cntx(c), cntx(b))match(c)=∑x​min(cntx​(c), cntx​(b)),若 match⁡(c)≧kmatch(c)≧k 则符合要求。

输入描述:

第一行输入整数 t(1≦t≦104)t(1≦t≦104)------测试用例组数。

每个测试用例:

• •​一行三个整数 n,m,k(1≦k≦m≦n≦2×105)n,m,k(1≦k≦m≦n≦2×105);

• •​一行 nn 个整数 a1...an (1≦ai≦106)a1​...an​ (1≦ai​≦106);

• •​一行 mm 个整数 b1...bm (1≦bi≦106)b1​...bm​ (1≦bi​≦106)。

输入保证所有测试用例的 nn 之和、mm 之和均不超过 2×1052×105。

输出描述:

对每个测试用例输出一行整数,表示满足条件的子段数量。

示例1

输入:

复制代码
1
4 1 1
4 1 5 6
6

复制输出:

复制代码
1
cpp 复制代码
#include <iostream>
#include <vector>
#include <map>

using namespace std;

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> a(n);
    map<int, int> mapB;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for (int i = 0; i < m; ++i) {
        int val;
        cin >> val;
        mapB[val]++;
    }

    map<int, int> mapA;
    int current_match = 0;
    int ans = 0;

    // 初始化第一个窗口
    for (int i = 0; i < m; ++i) {
        mapA[a[i]]++;
    }

    for (auto const& [val, countB] : mapB) {
        if (mapA.count(val)) {
            current_match += min(mapA[val], countB);
        }
    }

    if (current_match >= k) {
        ans++;
    }

    // 滑动窗口
    for (int i = m; i < n; ++i) {
        int remove_val = a[i - m];
        int add_val = a[i];

        // 处理移出窗口的元素
        if (mapB.count(remove_val)) {
            if (mapA[remove_val] <= mapB[remove_val]) {
                current_match--;
            }
        }
        mapA[remove_val]--;
        if (mapA[remove_val] == 0) {
            mapA.erase(remove_val);
        }

        // 处理加入窗口的元素
        if (mapB.count(add_val)) {
            if (mapA.count(add_val) < 1 || mapA[add_val] < mapB[add_val]) {
                current_match++;
            }
        }
        mapA[add_val]++;

        if (current_match >= k) {
            ans++;
        }
    }
    cout << ans << endl;
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
相关推荐
汉克老师29 分钟前
GESP2026年9月认证C++七级( 第三部分编程题(2、括号序列))精讲
c++·gesp·小学生·学c++编程
w_zero_one36 分钟前
链表(4)
java·数据结构·算法
吠品40 分钟前
GitHub 周榜拆解:决策小模型扎堆上位
c语言·开发语言·算法
Ivanqhz42 分钟前
MLA、DSA、CSA、HCA
人工智能·算法·机器学习
嘎嘎风2 小时前
MiniMind 学习笔记之 07 模型怎么学会猜词(旋钮是怎么被拧动的)
算法·源码阅读
和裕2 小时前
定制纸箱刀模费全解析:费用定义与可减免合作场景
大数据·运维·网络·人工智能·算法
白山编程大哥2 小时前
C语言篇:语法进阶
c语言·数据结构·算法
jimy12 小时前
虚函数vtable,链接时看到构造函数,linker把符号地址写入vtable(三)
开发语言·c++
Doubbbbbbble云3 小时前
基于流处理框架的实时算法实现策略4
算法
2601_962885723 小时前
如何用 Python 计算 ROC 变动率指标做动量分析?
开发语言·python·算法