蓝桥杯2023年第十四届省赛真题-子串简写

 由于是第一次打算法类竞赛所以不太熟悉流程导致该拿分的没拿到,所以写篇博客来警醒自己。

直接说思路吧:

我们可以先将每个c1字符的每个出现位置和c2字符的每个出现位置记录下来,然后通过枚举c1字符的出现位置来用二分查找对应c1字符位置出现时c2字符应该在哪个位置出现。然后求和c2字符出现的总次数去减去枚举每个c1字符时c2字符正确的位置就可以了。

图解:

 

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int nec1[500100];
int c1dx = 0;
int c2dx = 0;
int nec2[500100];
int main()
{
    int k;
    cin >> k;
    string str;
    cin >> str;
    str = "1" + str;
    char c1, c2;
    cin >> c1 >> c2;
    for (int i = 1; i < str.length(); i++) {
        //记录c1字符所有出现的位置
        if (str[i] == c1) {
            nec1[c1dx] = i;
            c1dx++;
        }
        //记录c2字符所有出现位置
        if (str[i] == c2) {
            nec2[c2dx] = i;
            c2dx++;
        }
    }

    long long ans = 0;
    //枚举c1字符出现的位置
    for (int i = 0; i < c1dx; i++) {
        //二分查找c2字符出现的位置的合法位置
        auto dx = lower_bound(nec2, nec2 + c2dx, nec1[i] + k-1);
        //没有找到情况
        if (dx == nec2 + c2dx)continue;
        //找到了
        int t = dx - nec2;
        //加上总合法个数
        ans += c2dx - t;
    }

    cout << ans << endl;
    return 0;
}

若有雷同纯属意外。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值