【hdu5056】Boring count

之前一直没接触过尺取法,感觉还是可以理解的

我们可以设置一个完全满足题目要求的区间,然后从前往后不断加入元素,每加入一个元素,我们就要维护这个区间的正确性,如果加入新的元素之后,区间不满足要求,则将区间左端逐渐向右,直至这个区间符合题意为止,这样的做法是o(n)的

在这个题上,我们不断加入新的字母,如果发现这个区间不合法以后,则将其左端点不断右移,我们可以将其理解为,现在所求的,是以i这个位置为结尾的满足条件的子串数量,如果现在这个区间不合法,则说明左端点已经没有用了(因为之前需要它的时候已经都处理过了,向后走加入的字母更多,更与它无关),将其弹出

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int he,ta,len,t,k,tot[30];
long long ans;
char s[100010];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s+1);
        len=strlen(s+1);
        he=1,ta=0,ans=0;
        scanf("%d",&k);
        memset(tot,0,sizeof(tot));
        for(int i=1;i<=len;i++)
        {
            int lin=s[i]-'a';
            tot[lin]++,ta++;
            if(tot[lin]>k&&he<ta)//如果一种字母的个数超过k,则说明区间不合法,将左端点向右移动 
            {
                while(tot[lin]>k)//直至这种字母个数不超过k 
                    tot[s[he++]-'a']--;
            }
            ans+=(ta-he+1);//如果这个区间都满足条件了,那么在这个区间里,所有以i为结尾的子串也就全部满足条件,都应加进答案 
        }
        cout<<ans<<endl;
    }
}

 

posted @ 2017-10-29 16:06  那一抹落日的橙  阅读(201)  评论(0编辑  收藏  举报