HDU-5672 String(尺取法)

题意

给定一个只有小写字母字符串 S S ,求存在多少个子串至少包含了 k 种子母。
1length(S)1000000 1 ≤ l e n g t h ( S ) ≤ 1000000

思路

开一个 cnt c n t 数组记录此时每种字母出现的次数,并用 cur c u r 实时记录不同字母的个数。如果右移使此字母的 cnt c n t 值由零变成一, cur c u r 值就加一;如果左移使此字母的 cnt c n t 值由一变成零, cur c u r 值就减一。右移至 curk c u r ≥ k 时累计答案。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
typedef long long LL;
using namespace std;
char str[1000003];
int cnt[28];

int main()
{
    int T,k;
    scanf("%d",&T);
    while(T--)
    {
        memset(cnt,0,sizeof(cnt));
        scanf("%s%d",str+1,&k);
        int n=strlen(str+1),R=0,cur=0;
        LL ans=0;
        FOR(L,1,n)
        {
            while(L>R||R<n&&cur<k)
            {
                if(cnt[str[++R]-'a']==0)cur++;
                cnt[str[R]-'a']++;
            }
            if(R>n)break;
            if(cur>=k)ans+=n-R+1;
            cnt[str[L]-'a']--;
            if(cnt[str[L]-'a']==0)cur--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值