【HDU - 5672】String(尺取法)

版权声明:欢迎学习我的博客,希望ACM的发展越来越好~ https://blog.csdn.net/qq_41289920/article/details/82948127

题干:

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);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/82948127