hdoj 5672 String (尺取法)

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



你可能感兴趣的:(hdoj 5672 String (尺取法))