String HDU - 5672 (尺取)

String

 题目链接:HDU - 5672 

题意:有一条只由小写字母构成的字符串,问有多少子串中包含不少于k个不同字符;

思路:若以l为起点的区间[l, r]中,有k个不同字符,且r处的字符就是第k个不同的字符,那么r后边的区间也一定 至少k个不同字符;

那么,以l为起点的区间中,包含至少k个不同字符的区间有n-r个(n是原串长度,下标由0开始);

就用尺取法维护这样一个区间;

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
char s[maxn];
int vis[30], k, cnt;
bool check(int x){
	if(vis[s[x]-'a']) return cnt<k;
	return cnt+1<k;
}
int main(){
	int T;
	scanf("%d", &T);
	while(T--){
		scanf("%s", s);
		scanf("%d", &k);
		memset(vis, 0, sizeof(vis));
		long long ans=0;
		int len=strlen(s);
		vis[s[0]-'a']++;
		cnt=1;
		for(int i=0, j=0; i<len; i++){
			while(check(j+1)&&j+1<len){
				j++;
				if(vis[s[j]-'a']==0) cnt++; 
				vis[s[j]-'a']++;
			}
			if(j>=len-1) break;
			ans+=(len-j-1);
			vis[s[i]-'a']--;
			if(vis[s[i]-'a']==0) cnt--;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sirius_han/article/details/81138827