智乃的密码题解报告
标签:尺取
来源:牛客网
解题思路:
根据题目所给N的范围 自然想到尺取和二分两种算法
下面选择用尺取来做
枚举子串的左端点,移动右指针同时统计种类个数,直到满足种类数量为止,
随后与字符串最短长度和最长长度取交集,找到满足条件的右端点的区间
满足时间复杂度O(N)
代码基本照抄了某大佬的
大佬的代码实在是简洁又美观
另外学会了如下处理方式
(cnt[0] > 0) + (cnt[1] > 0) + (cnt[2] > 0) + (cnt[3] > 0) < 3
让我自己实现同效果得打十多行
代码实现:
#include <bits/stdc++.h>
using namespace std;
int cnt[4];
int main(){
string s;
int n,L,R;
cin>>n>>L>>R;
cin>>s;
vector <int> a(n);
for(int i=0;i<n;i++){
if(isdigit(s[i])) a[i]=0; //数字
else if(islower(s[i])) a[i]=1;//小写
else if(isupper(s[i])) a[i]=2;//大写
else a[i]=3;
}
long long ans=0;
for (int i=0,j=0;i<n;i++) {
while (j <= n && (cnt[0] > 0) + (cnt[1] > 0) + (cnt[2] > 0) + (cnt[3] > 0) < 3) {
//cnt > 0 返回值为1或0
if (j < n) {
cnt[a[j]]++;
}
j++;
}
int l = max(j, i + L)-1;
int r = min(n, i + R)-1;
ans += max(0, r - l + 1);
cnt[a[i]]--;
}
cout<<ans<<endl;
}