Best Coder 1003 string(dp)

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
分析:

数学组合,直接模拟计数。 按顺序遍历字符串,记录出现的不同字母的个数cnt,和每种字母出现的数量。 当cnt==k时,以当前字符串为子串的子串共有len-i个。然后将最左边的减去,依次记录下去。


#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
char s[1000010];
int v[30];
int main()
{
    int k,t,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%d",s,&k);
        int len=strlen(s);
        int c=0,l=0;
        long long ans=0;
        memset(v,0,sizeof(v));
        for(i=0; i<len; i++)
        {
            int t=s[i]-'a';  //转化为数字,便于计算
            if(v[t])          //如果出现过此字符,标记出现过几次
                v[t]++;
            else      //如果没有出现过此字符,标记出现,字符数加1
            {
                v[t]++;
                c++;
            }
            if(c==k)
            {//如果字符数等于要求的那个数,以当前字符串为子串的子串共有len-i个
                ans+=len-i;
                while(1)
                {
                    t=s[l]-'a';  //把字符取出
                    v[t]--;  //数量减去一个
                    l++;  //再处理下一个
                    if(!v[t])  //如果字符的次数不为1
                    {
                        c--;     //把字符数-1
                        break;
                    }
                    else  //如果只有一个,再加一次
                        ans+=len-i;
                }//直到左边的字符串减掉完
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值