BestCoder #81 Div2 C String(尺取法)

题目链接:
BestCoder #81 Div2 C String
题意:
有一个10≤长度≤1,000,000 的字符串,仅由小写字母构成。求有多少个子串,包含有至少k(1≤k≤26)个不同的字母?
分析:
假设从s[0]到s[i]正好第一次满足出现K个不同的字母,那么从i开始到字符串尾都是满足的,一共是len-i个。0–i范围内的K个不同字母的子串还是可以缩短的,从0开始向后移动直到一个字母s[i]恰好出现一次,如果不包含s[j]一定只含有K-1个不同的字母,所以j是起始端的上限,一共是j-st+1个,所以这一次一共有(j-st+1)*(len-i)个不同的子串,更新st为j+1,i向后继续搜索。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
using namespace std;
const int MAX_N=(int)(1e6)+10;

int T,K,vis[30];
char s[MAX_N];

int main()
{
    freopen("81Cin.txt","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%s%d",s,&K);
        int len=strlen(s);
        int st=0,total=0;
        long long ans=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<len;i++){
            if(vis[s[i]-'a']==0){
                vis[s[i]-'a']=1;
                total++;
                if(total==K){
                    int j=st;
                    for(j=st;vis[s[j]-'a']!=1;j++){
                        vis[s[j]-'a']--;
                    }
                    //printf("st=%d j=%d i=%d\n",st,j,i);
                    ans+=(j-st+1)*(len-i);
                    st=j+1;
                    total--;
                    vis[s[j]-'a']=0;
                }
            }else {
                vis[s[i]-'a']++;
            }
        }
        printf("%lld\n",ans);
    }   
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值