2022牛客寒假算法训练营3 I - 智乃的密码 (自己的一点理解和优化)

本文介绍了一道编程竞赛题目,涉及到字符串处理和二分查找算法。题目要求在给定字符串中找到满足特定条件的子串数量,即子串中至少包含四种字符类别中的三种且每种至少出现3次。通过分析,可以使用二分搜索来确定每个条件的合法区间,并优化代码实现,如利用前缀和和标记数组。最终,通过遍历字符串并计算符合条件的子串数量得出答案。
摘要由CSDN通过智能技术生成

题目链接:https://ac.nowcoder.com/acm/contest/23478/I
题面:题面
思路:可以参考这里
以下摘自官方题解
同时这6个条件在固定所选子串的其中一个端点后,另一个端点的合法性是单调的。
所以可以使用二分或者尺取的方式直接判断每一个条件的合法区间。

一点理解和优化:
1)首先为什么border()的返回值为tmp[1];仔细阅读题干,题目要求密码中至少包含四类字符的3种,而sort默认为升序,所以只要tmp[1] > 0 ,那么一定会存在3种不同符号满足要求;而如果border返回值为0,那么rr一定 <= 0,而 ll >= 1,所以calcu返回值为0;

2)在官方题解种通过前缀和数组和一层循环来更新某一类字符出现的位置,其实我们直接将该类字符的下标,用一个标记数组mar来记录就行了

3)另外,ans应该开long long ,不然会被卡。

具体参考代码实现

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
char s[N];
int l, r, n;
long long ans;
int mar[4];

int type(char ch){
    if(ch >= '0' && ch <= '9')  return 0;
    if(ch >= 'a' && ch <= 'z')  return 1;
    if(ch >= 'A' && ch <= 'Z')  return 2;
    else    return 3;
}

int border(){
    int tmp[4];
    memcpy(tmp, mar, sizeof(mar));
    sort(tmp, tmp + 4);
    return tmp[1];
}

int calcu(int x){
    int ll = 1, rr = n;
    ll = max(ll, x - r + 1);
    rr = min(rr, x - l + 1);
    rr = min(rr, border());
    return ll <= rr ? rr - ll + 1 : 0;
}

int main(){
    scanf("%d%d%d", &n, &l, &r);
    scanf("%s", s + 1);
    for(int i = 1; i <= n; ++i){
        mar[type(s[i])] = i;
        ans += calcu(i);
    }
    printf("%lld\n", ans);
    system("pause");
    return 0;
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值