hdu 5056 Boring count

来源:互联网 发布:黑客帝国3矩阵帝国 编辑:程序博客网 时间:2024/05/16 01:51

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5056

题目的意思是,给你一个不超过100000的只包含小写字母的串。。问有多少子串,它里面的所有字母个数都不超过k。。这是BestCoder 12 Div2 1003题。 比赛的时候没有做出来。。

当时想的是如何从里面减去一些,然后的到答案。。。因为我们可以很容易是计算出他是子串有(n+1) * n / 2个。。。。。表示,当时有sb了那么些时间。。。当一种思路堵塞时候,本应该去想另一种思路,我们却在一直死磕当时的想法。。我想这就是我们思维存在的错误吧。。

正确的解法:(摘之官方题解,但是,我们发现了他的错误之处。。)

1003 Boring count枚举字符串下标i,每次计算以i为结尾的符合条件的最长串。那么以i为结尾的符合条件子串个数就是最长串的长度。求和即可。计算以i为结尾的符合条件的最长串两种方法:1.维护一个起点下标startPos,初始为1。如果当前为i,那么cnt[str[i]]++,如果大于k的话,就while( str[startPos] != str[i] ) cnt[str[startPos]]--, startPos++; 每次都保证 startPos~i区间每个字母个数都不超过k个。ans += ( i-startPos+1 )。 时间复杂度O(n)2.预处理出所有字母的前缀和。然后通过二分找出以i为结尾的符合条件的最长串的左边界。时间复杂度O(nlogn),写的不够好的可能超时。Code:
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <string>#include <vector>using namespace std;#define INT long longconst int N = 30;int main(){    int T;    cin >> T;    while(T --){        string str;        cin >> str;        INT len = str.size(), dp[N], k;        cin >> k;        memset(dp, 0, sizeof(dp));        INT ans = 0, beginp = 0;        for(INT i = 0; i < len; i ++){            dp[str[i] - 'a'] ++;            if(dp[str[i] - 'a'] > k){                for(; beginp <= i; beginp ++)                if(str[beginp] == str[i]){                    dp[str[beginp] - 'a'] --;                    beginp ++;                    break;                }                else {                    dp[str[beginp] - 'a'] --;                }            }//            printf("%I64d %I64d\n", beginp, i);            ans += i - beginp + 1;        }        cout << ans << endl;    }    return 0;}

我们做BC,CF最后的hack时间。。 是为了锻炼我们读代码的能力,不可缺少的。。也正是我所欠缺的。。下次,hack时间要认真。。

0 0
原创粉丝点击