问题描述
有一个 10≤长度≤1,000,000 的字符串,仅由小写字母构成。求有多少个子串,包含有至少k( 1≤k≤26 )个不同的字母?
输入描述
输入包含多组数据. 第一行有一个整数T (1≤T≤10), 表示测试数据的组数. 对于每组数据:
第一行输入字符串S。 第二行输入一个整数k。
输出描述
对于每组数据,输出符合要求的子串的个数。
输入样例
2
abcabcabca
4
abcabcabcabc
3
输出样例
0
55
思路:
106
,
O(n2)
肯定会超时;
找出一个包括k种字母的最小子串,则子串加左右必定也符合,可以直接算出包含子串的总情况数;
为了排除重复情况,限制r为最小子串右边界,l为左边界,从左到右递推r,算出相应的l,ans+=l。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e6 + 10;
char s[MAXN];
int al[27];
int main(int argc, char const *argv[])
{
int t;
scanf("%d", &t);
while(t--)
{
int k;
scanf("%s", s);
scanf("%d", &k);
long long ans = 0;
int l = 0, r = 0, j = 0;
int len = strlen(s);
memset(al, 0, sizeof(al));
for(r = 0; r < len; r++)
{
if(!al[s[r]-'a'])
j++;
al[s[r]-'a']++;
if(j < k)
continue;
while(j > k || al[s[l]-'a'] > 1)
{
al[s[l]-'a']--;
if(!al[s[l]-'a'])
j--;
l++;
}
ans += l + 1;
}
printf("%I64d\n", ans);
}
return 0;
}