您的位置:首页 > 其它

hdoj 5672 String (尺取法)

2016-04-26 21:25 148 查看
Description

There is a string $S$.$S$ only contain lower case English character.$(10 \leq length(S) \leq 1,000,000)$

How many substrings there are that contain at least $k(1 \leq k \leq 26)$ distinct characters?

Input

There are multiple test cases. The first line of input contains an integer $T (1\leq T\leq 10)$ indicating the number of test cases. For each test case:

The first line contains string $S$.

The second line contains a integer $k(1 \leq k \leq 26)$.

Output

For each test case, output the number of substrings that contain at least $k$ dictinct characters.

Sample Input

2
abcabcabca
4
abcabcabcabc
3


Sample Output

0
55


题目大意:

有一串字符串,然后给一个数字t,求包含t个不同的字符的字串个数。

解题思路:

尺取法,也叫双指针法,顾名思义,就是两个指针指向字串的起始和结束的地方。

解决此题是,因为要求包含不同单词的字串,如果{i ,j} 包含t个不同字符的个数,那个{i,k}(s(字串长度)>=k >= j)都包含t个不同字符的个数,设置一个数,表示最小右端点,然后依次更新最小左右端点,每次加上字串的个数,字串的个数就是字符串的长度减去最小右端点。

代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
char s[1000010];
int main()
{
int a[27], t, k, i;
long long sum;
scanf("%d",&t);
while(t--)
{
scanf("%s%d",s,&k);
memset(a, 0, sizeof(a)); // 记录字串中各个字符的个数
int End, con;
con = 0;End = -1;//End表示最小右端点
sum = 0;
int len = strlen(s);
for(i = 0; i < strlen(s); i++)//i就是最小左端点。
{
while(con != k && (End < len))
{
End++;
if(End >= len)
break;
a[s[End] - 'a']++;
if(a[s[End] - 'a'] == 1)//如果刚刚数过加入一个新的字符
con++;  //字符个数加一。

}
if(End >= len)
break;
sum =sum + (len - End);//每次加上子串的个数
a[s[i] - 'a']--;//最小左端点左移
if(a[s[i] - 'a'] == 0)//如果最小左端点代表的字符去掉之后字串字符的个数没有了,字符个数减一
con--;

}
printf("%lld\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: