HDU 5672 String 【尺取】

<题目链接>

题目大意:
给定一个只由26个小写字母组成的字符串,现在问你至少包含k个不同字母的连续子序列总数有多少。

解题分析:
经仔细研究,我们发现,每次尺取到符合要求的最小区间,然后将区间的右端点一直移动到字符串的末尾,右端点每移动一位,又能组成一个符合条件的字符串序列,并且,因为每次尺取的过程中,左指针会不断向右移动一位,所以这样的求解能够是的最终的答案不重不漏。

#include <bits/stdc++.h>
using namespace std;

char str[int(1e6+5)];
int num[30];

inline int differ(){ int ans=0;for(int i=0;i<26;i++)if(num[i])ans++;return ans; }
int main(){
    int T;scanf("%d",&T);while(T--){
        getchar();
        memset(num,0,sizeof(num));
        scanf("%s",str);int len=strlen(str);
        int k;scanf("%d",&k);
        int l=0,r=0;long long ans=0;   //int会溢出
        while(true){
            while(differ()<k && r<len){
                num[str[r++]-'a']++;    //第r个元素的字母种类++,并且右指针右移
            }
            if(differ()<k)break;
            ans+=len-r+1;  //仔细研究之后,我们发现,其实就是尺取过程中每次符合条件的区间再加上右端点一直向右移动到末尾的所有序列总数
            num[str[l++]-'a']--;    //左指针追赶
        }           
        printf("%lld
",ans);
    }
}

2019-03-03

原文地址:https://www.cnblogs.com/00isok/p/10466037.html