hdu-5672 String 尺取法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5672

题意:

        给你一个字符串,要你找出里面含有至少k个不同字符的子串个数。

做法:

       经典尺取,从左往右枚举左边界,用一个指针r代表当前的最小符合条件的右界,当l~r里刚好有k个不同字母且r在这个l下最小的时候,那么以l为左边界的子串就有len-r+1个(用1作为第一个下标),所以只要一直推过来,时间复杂度就从原来的O(N^{2})降到了O(N).

      代码底子变弱了,留个板子,小细节注意一下。加油!


#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=1000005;
char s[maxn];
int a[maxn],k,vis[35];
ll ans;
int main(){
    int t;
    cin>>t;
    while(t--){
        memset(vis,0,sizeof(vis));
        scanf("%s%d",s+1,&k);
        int n=strlen(s+1);
        for(int i=1;i<=n;i++){
            a[i]=s[i]-'a'+1;
        }
        int r=0,num=0;ans=0;
        for(int l=1;l<=n;l++){
            while(r+1<=n&&num<k){
                r++,vis[a[r]]++;
                if(vis[a[r]]==1) num++;
            }
            if(num==k) ans+=n-r+1;
            vis[a[l]]--;
            if(vis[a[l]]==0) num--;
        }
        printf("%lld\n",ans);
    }

    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值