J.陈梓豪学长的密码
题目描述:
输入描述:
输出描述:
示例:
思路:
首先使用一个 flag[5] 数组判断字符种类,flag[1] ~ flag[4] 表示四种字符,flag[0] 表示已有的字符种类。
要求求出符合条件的子串密码,我们可以使用快慢指针来一步步遍历字符串,每次符合条件则加一,最后输出结果。
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, L, R;
int flag[5];
char s[N];
//判断字符的函数
int P(int x)
{
if (s[x] >= 'A' && s[x] <= 'Z')
return 1;
if (s[x] >= 'a' && s[x] <= 'z')
return 2;
if (s[x] >= '0' && s[x] <= '9')
return 3;
//其他字符则返回4
return 4;
}
int main()
{
//初始化
scanf("%d %d %d\n", &n, &L, &R);
scanf("%s", s + 1);
//快慢指针
int l = 1, r = 0;
int ans = 0;
while (l <= n){
while (r - l + 1 <= R && r < n){
//右指针先右移一位后,判断是哪种字符
int p = P(r++);
//统计字符种类,若没有该字符,则加一,标记为已存在
if (flag[p] == 0)
flag[0]++;
//该字符数量加一
flag[p]++;
//若子串中字符种类有三种及以上,且符合合法字符的长度限制
if (flag[0] >= 3 && r - l + 1 >= L){
ans += min(n - r + 1, R - (r - l + 1) + 1);
break;
}
}
//右移左指针
int p = P(l++);
//若该种字符已存在,右移,字符种类减一
if (flag[p] == 1)
flag[0]--;
//字符数量减一
flag[p]--;
if (flag[0] >= 3 && r - l + 1 >= L)
ans += min(n - r + 1, R - L + 1);
}
printf("%d\n", ans);
return 0;
}