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

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
  
  
3 abc 1 abcabc 1 abcabc 2
 

Sample Output
  
  
6 15 21
 
题目链接: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值