HDU 5056 Boring count(窗口滑动法或尺缩法)

来源:互联网 发布:centos源码 编辑:程序博客网 时间:2024/05/22 12:58

Boring count

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1003    Accepted Submission(s): 413


Problem Description
You are given a string S consisting of lowercase letters, and your task is counting the number of substring that the number of each lowercase letter in the substring is no more than K.
 

Input
In the first line there is an integer T , indicates the number of test cases.
For each case, the first line contains a string which only consist of lowercase letters. The second line contains an integer K.

[Technical Specification]
1<=T<= 100
1 <= the length of S <= 100000
1 <= K <= 100000
 

Output
For each case, output a line contains the answer.
 

Sample Input
3abc1abcabc1abcabc2
 

Sample Output
61521
 
题目链接:hdu 5056

题目大意:
输入T表示测试数组个数,每组数据第一行输入一串字符串(注意只包含小写字符)。第二行输入k,表示满足条件的子串中出现频率最高的字母频率不超过k。(注意:子串内容相同但位置不同的算是不同的子串)。

解题思路:
由于字符串之间可以重复,并且区分子串的只有子串的首位地址。

对区间[i,j],i表示满足条件的最左边的边界。答案加上当前区间的长度j-i+1。
区间向右走一步,j=j+1。判断频数是否>k,如果大于则向右移动i知道当前聘书<=k, 否则记录答案继续向右移动j。

刚开始做这道题时也是没想到这种方法,赛后看了题解以后才会做。

AC代码:
    #include <iostream>    #include <stdio.h>    #include <cstring>    #include <cmath>    #include <algorithm>    #include <queue>    #include <stack>    using namespace std;    typedef long long LL;    typedef unsigned long long ULL;    int a[100050];//记录输入的字符串    int index[28];//记录频数    int main()    {        int t,k;        string str;        LL ans=0;        int flag=0;        cin >> t;//测试组数        while(t--)        {            memset(index,0,sizeof(index));//初始化记录当前段频数数组            cin >> str;            cin >> k;//输入最大频数k            int n=str.length();//字符串的长度            int cnt=1;            for(int i=0;i<n;i++)            {                a[i]=str[i]-'a';            }            int i=0;//初始区间的左边界为0            ans=0;//初始结果为0            for(int j=0;j<n;j++)//遍历区间的右边界j            {                index[a[j]]++;//将当前j所在的位置的字母频数加一                while(index[a[j]]>k)//当前区间不满足最大频数<=k时向右移动i进入循环,直到满足条件                {                    index[a[i]]--;//i向右移动把i所在位置的字母频数减去                    i++;//i向右移动                }                int tmp=j-i+1;                ans+=tmp;//经过上述循环以后当前区间满足条件,把结果加到答案ans中            }            cout << ans << endl;        }        return 0;    }



0 0
原创粉丝点击