zoukankan      html  css  js  c++  java
  • HDU 5056 Boring count(BestCoder Round #11 (Div. 2))

    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

    题意:给出一个字符串s和一个整数k,问有多少s的子串满足条件,条件是子串中每个字母出现的个数不能大于k(只有小写字母)。

    这里用到一个公式,一个长度为n的字符串的连续子串的个数为1+2+3+……+n。证明:举例如abcabc:我们可以分别得到该字符串长度为1,2,3,4,5,6的子串:

    1:a     b     c     a     b     c;

    2:ab     bc     ca     ab     bc;

    3:abc     bca     cab     abc;

    4:abca      bcab     cabc;

    5:abcab     bcabc;

    6:abcabc;

    不难发现连续子串的个数和是1+2+3+……+n。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<math.h>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    
    const int N=1e5+10;
    const int INF=0x3f3f3f3f;
    const int MOD=1e9+7;
    
    typedef long long LL;
    
    char s[N];
    int vis[N]; ///标记序号为i的字母出现的次数
    
    int main ()
    {
        int T, k, i, j;
        LL ans; ///这里必须用LL,不然会wa
    
        scanf("%d", &T);
    
        while (T--)
        {
            scanf("%s %d", s, &k);
    
            j = 0; ///当发现一个字母出现的次数>k时,j的值会改变
            ans = 0;
            memset(vis, 0, sizeof(vis));
    
            for (i = 0; s[i] != ''; i++)
            {
                vis[s[i]-'a']++;
    
                if (vis[s[i]-'a'] > k)
                {
                    while (s[j] != s[i]) ///举例:bcaacb(k==1),当我们找到第二个a时发现a出现的次数大于k了,首先之前的bca已经算出了子串个数1+2+3,所以现在的bc的次数需要减1,j需要移到前一个a
                    {
                        vis[s[j]-'a']--;
                        j++;
                    }
    
                    vis[s[i]-'a']--; ///还是上面的例子由于现在a的次数大于k,那么我们也需要将a的次数减1,j指向现在的a(当然举例:abcabc也是成功的,只是这时没有经过while循环那一步)
                    j++;
                }
    
                ans += i-j+1; ///这里计算子串的个数,至于为什么只加上字符的个数,举例:abc:在a的时候我们会加1(可以看做加上了a这个子串),在b的时候加2(本来ab有三个子串:a,b,ab,但是之前加了a,不能重复,所以加2),那么在c的时候同理加3就好了
            }
    
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Hadoop2.0 HA集群搭建步骤
    了解何为DML、DDL、DCL
    搭建Hadoop平台(新手入门)
    周记1
    IT小小鸟
    Python中的函数修饰符
    python_类方法和静态方法
    Python的log模块日志写两遍的问题
    python——装饰器例子一个
    初识HIVE
  • 原文地址:https://www.cnblogs.com/syhandll/p/4924253.html
Copyright © 2011-2022 走看看