<a target=_blank href="http://acm.hdu.edu.cn/showproblem.php?pid=5056" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">http://acm.hdu.edu.cn/showproblem.php?pid=5056</a>

所有字母个数都不超过k的字串数目

比赛时候用模拟+组合数学过的,是O(2*26*N)的复杂度,但是没有正解快

遍历每个恰好符合条件的[i,j],其中若包含[i,jj]其中jj是上次计数的最远的j,就+一次i~j -一次i~jj

过的比较险

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include<set>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
LL gcd(LL a,LL b){ return b == 0? a:gcd(b,a%b);}
char s[100005];
int n,k;
LL ans;
int cnt[26][100005];
void work()
{
//clr0(cnt);
scanf("%s",s);
RD(k);
n = strlen(s);
for(int i = 0;i < 26;++i)
memset(cnt[i],0,sizeof(int)*(n+1));
ans = 0;
for(int i = 1;i <= n;++i){
for(int l = 0;l < 26;++l){
cnt[l][i] = cnt[l][i-1];
}
cnt[s[i - 1] - 'a'][i]++;
}
int mx;
for(int i = 0,j = 1,jj = 0;i <= n;++i){
while(j <= n){
mx = 0;
for(int l = 0;l < 26;++l){
mx = max(mx,cnt[l][j] - cnt[l][i]);
}
if(mx > k)
break;
++j;
}
if(j == jj)
continue;
if(mx > k){
ans += 1LL*(j-i)*(j-i-1)/2;
if(jj > i)
ans -= 1LL*(jj-i)*(jj-i-1)/2;
jj = j;
//cout<<ans<<endl;
}
else if(j > n){
ans += 1LL*(n-i)*(n-i+1)/2;
if(jj > i)
ans -= 1LL*(jj-i)*(jj-i-1)/2;
break;
}
}
printf("%I64d\n",ans);
}
int main() {
int _;
RD(_);
while(_--){
work();
}
return 0;
}

正解果然要快很多

枚举字符串下标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),写的不够好的可能超时。
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include<map>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
char s[100005];
int n,k;
LL ans;
int cnt[256];
void work()
{
scanf("%s",s+1);
RD(k);
n = strlen(s+1);
clr0(cnt);
ans = 0;
int st = 1;
for(int i = 1;i <= n;++i){
cnt[s[i]]++;
if(cnt[s[i]] > k){
while(1){
cnt[s[st]]--,st++;
if(s[st-1] == s[i])
break;
}
}
ans += i - st + 1;
}
printf("%I64d\n",ans);
}
int main() {
int _;
RD(_);
while(_--){
work();
}
return 0;
}

												

hdu 5056 所有字母数都<=k的子串数目的更多相关文章

  1. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  2. 《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数

    题目 在其他数都出现k 次的数组中找到只出现一次的数 java 代码 package com.lizhouwei.chapter7; /** * @Description: 在其他数都出现k 次的数组 ...

  3. hdu 5056 Boring count (类似单调队列的做法。。)

    给一个由小写字母构成的字符串S,问有多少个子串满足:在这个子串中每个字母的个数都不超过K. 数据范围: 1<=T<= 1001 <= the length of S <= 10 ...

  4. 用js编程输出100以内所有的质数和个数(提示:一个大于1的自然数,除了1和它本身外,不能被其他自然数整除的数都是质数)

    <script type="text/javascript"> for(var i = 3; i <= 100; i ++) {//控制2-100所有的数i fo ...

  5. 75 int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数。[2行核心代码]

    [本文链接] http://www.cnblogs.com/hellogiser/p/single-number-of-array-with-other-three-times.html [题目] i ...

  6. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

      HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...

  7. 一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

    一个int数组, 比如 array[],里面数据无任何限制,要求求出 所有这样的数array[i],其左边的数都小于等于它,右边的数都大于等于它.能否只用一个额外数组和少量其它空间实现. 分析:这题很 ...

  8. JS 实现计算一段文字中的字节数,字母数,数字数,行数,汉字数。

    看到了匹配,第一个想到了用正则表达式,哈哈,果然很方便.不过正则表达式高深莫测!我还没有研究明白啊..目前学了点皮毛.代码如下: <!DOCTYPE html PUBLIC "-//W ...

  9. 给自己名字abel.这个好,怎么字母排序都第一

    给自己名字abel.这个好,怎么字母排序都第一

随机推荐

  1. andorid 表格布局

    tablelayout.xml表格布局 <?xml version="1.0" encoding="utf-8"?> <TableLayout ...

  2. hdu 4004 (二分加贪心) 青蛙过河

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4004 题目意思是青蛙要过河,现在给你河的宽度,河中石头的个数(青蛙要从石头上跳过河,这些石头都是在垂 ...

  3. (O)JS高阶函数应用——函数节流

    在一些函数需被频繁调用的场景,如:window.onresize.mousemove.scroll滚动事件.上传进度等等,操作频繁导致性能消耗过高,而造成浏览器卡顿现象,我们可以通过函数节流的方式解决 ...

  4. IOS 将图片转换为圆角图

    UIImage+wiRoundedRectImage.h #import <UIKit/UIKit.h> @interface UIImage (wiRoundedRectImage) + ...

  5. MySQL连接、登录、密码等

    官方教程:https://dev.mysql.com/doc/refman/8.0/en/ 链接数据库,通过指定 -h 参数可以连接网络上的数据库 mysql -u 用户名 -h 服务器IP -P 端 ...

  6. include 指令和 include 动作引入 jsp 页面时中文乱码

    include指令:<%@ include file="new.jsp" %> include动作:<jsp:include page="new.jsp ...

  7. JSR 规范目录

    JSR 规范目录 一.Servlet 规范 1.1 Servlet 2.x 规范 1.2 Servlet 3.x 规范 - 注解和异步请求规范 每天用心记录一点点.内容也许不重要,但习惯很重要!

  8. 爬虫初窥day4:requests

      Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2 模块提供了你所需要的大多数 ...

  9. 服装类Web原型制作分享——Rodd & Gunn

    Rodd & Gunn是国外知名的服装类品牌,服装种类繁多,有衣服.帽子.穿戴饰品等. 本原型由国产Mockplus(原型工具)和iDoc(智能标注,一键切图工具)提供. 网站原型以图文排版为 ...

  10. 使用GZipStream压缩和解压文件

    最近做了一个用.NET里的GZipStream压缩解压缩gzip文件的小程序. GZipStream在System.IO.Compression底下,使用起来也很简单.虽然GZipStream是Str ...