题干:
There is a string SS.SS only contain lower case English character.(10≤length(S)≤1,000,000)(10≤length(S)≤1,000,000)
How many substrings there are that contain at least k(1≤k≤26)k(1≤k≤26) distinct characters?
Input
There are multiple test cases. The first line of input contains an integer T(1≤T≤10)T(1≤T≤10) indicating the number of test cases. For each test case:
The first line contains string SS.
The second line contains a integer k(1≤k≤26)k(1≤k≤26).
Output
For each test case, output the number of substrings that contain at least kk dictinct characters.
Sample Input
2 abcabcabca 4 abcabcabcabc 3
Sample Output
0 55
题目大意:
问有多少个 含有不少于k种字符的 子字符串。
解题报告:
尺取法,但是我是以右端点为一个记录,即 表示以第s[r]个字符为结尾,有多少个字符串满足。这种方法需要处理cnt>k的情况。
还有一种方法,每次统计以s[l]为起始的,有多少个子字符串满足,这种不需要考虑cnt>k的情况。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 1e6 +5;
char s[MAX];
int l,r,cnt,k,num[30];
ll ans;
int main()
{
int t;
cin>>t;
while(t--) {
scanf("%s",s+1);
scanf("%d",&k);
memset(num,0,sizeof num);
int len = strlen(s+1);
l = 1,r = 1;
cnt = 0;
ans = 0;
while(l<=len && r <=len) {
if(num[s[r] - 'a'] == 0) {
cnt++;
}
num[s[r] - 'a']++;
while(cnt > k) {
while(num[s[l]-'a'] >=1) {
num[s[l]-'a']--;
if(num[s[l]-'a']==0) cnt--;
l++;
if(cnt == k) break;
}
}
if(cnt == k) {
while(num[s[l]-'a'] > 1) num[s[l]-'a']--,l++;
ans += l;
}
r++;
}
printf("%lld\n",ans);
}
return 0 ;
}
/*
1
aabcc
3
*/
错误代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 1e6 +5;
char s[MAX];
int l,r,cnt,k,num[30];
ll ans;
int main()
{
int t;
cin>>t;
while(t--) {
scanf("%s",s+1);
scanf("%d",&k);
memset(num,0,sizeof num);
int len = strlen(s+1);
l = 1,r = 1;
cnt = 0;
ans = 0;
while(l<=len && r <=len) {
if(num[s[r] - 'a'] == 0) {
cnt++;
}
num[s[r] - 'a']++;
if(cnt == k) {
while(num[s[l]-'a'] > 1) num[s[l]-'a']--,l++;ans += l;
}
r++;
}
printf("%lld\n",ans);
}
return 0 ;
}
测试样例:
1
abc
2
应该输出3,但是输出了1。
AC代码2:(左端点的)
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000200];
int vis[30];
int main()
{
int t,k;
scanf("%d", &t);
while (t--)
{
scanf("%s%d", s,&k);
int len = strlen(s), sum = 0, r = -1;
long long ans = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < len; i++)
{
while (sum < k&&r+2<=len)
{
r++;
vis[s[r] - 'a']++;
if (vis[s[r] - 'a'] == 1)sum++;
}
if (sum==k)ans += len - r;
vis[s[i] - 'a']--;
if (vis[s[i] - 'a'] == 0)sum--;
}
printf("%I64d\n", ans);
}
}