问题描述
有一个 10\leq10≤长度\leq 1,000,000≤1,000,000 的字符串,仅由小写字母构成。求有多少个子串,包含有至少k(1 \leq k \leq 26)k(1≤k≤26)个不同的字母?
输入描述
输入包含多组数据. 第一行有一个整数T (1\leq T\leq 10)T(1≤T≤10), 表示测试数据的组数. 对于每组数据:
第一行输入字符串SS。
第二行输入一个整数kk。
输出描述
对于每组数据,输出符合要求的子串的个数。
输入样例
2
abcabcabca
4
abcabcabcabc
3
输出样例
0
55

有一个明显的性质:如果子串(i,j)包含了至少k个不同的字符,那么子串(i,k),(j < k < length)也包含了至少k个不同字符。

因此对于每一个左边界,只要找到最小的满足条件的右边界,就能在O(1)时间内统计完所有以这个左边界开始的符合条件的子串。

寻找这个右边界,是经典的追赶法(尺取法,双指针法)问题。维护两个指针(数组下标),轮流更新左右边界,同时累加答案即可。复杂度 O(length(S))。

------------------------------------------------

就像一把尺子一样,刚开始left = right = 0,然后先固定起点 left = 0,找到满足条件的尺子长度,然后left++,修改right长度,尺子长度不变,左边一旦往后加,右边也得往后加。

 #include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#include <cstring>
using namespace std;
typedef long long LL;
const int Max = + ;
char str[Max];
int cnt[];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int k, left, right;
scanf("%s", str);
scanf("%d", &k);
int len = strlen(str);
int num = ;
left = right = ;
memset(cnt, , sizeof(cnt));
LL ans = ;
while (left <= len - k)
{
while (num < k && right < len) // 一直找到 满足 k 个不同字符,即尺子的右端
{
if (cnt[ str[right] - 'a'] == )
{
num++;
}// 没访问才++;
cnt[ str[right] - 'a']++;
right++;
}
if (num == k) // 当字符个数 == k的时候就可以统计子串个数了
ans += len - right + ;
cnt[ str[left] - 'a' ]--; // 左边要往后移,所以如果left位置字符个数--之后为0那么 字符个数 num也得-1
if (cnt[ str[left] - 'a'] == )
num--;
left++;
}
printf("%I64d\n", ans);
}
return ;
}

HDU5672String(尺标法)的更多相关文章

  1. [ACM_其他] 总和不小于S的连续子序列的长度的最小值——尺缩法

    Description: 给定长度为n的整数数列,A[0],A[1],A[2]….A[n-1]以及整数S,求出总和不小于S的连续子序列的长度的最小值.如果解不存在,则输出0. Input: 输入数据有 ...

  2. 初窥构建之法——记2020BUAA软工个人博客作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 完成一次完整的软件开发经历并以博客的方式记录开发过程的心得掌握 ...

  3. KPI:Key Performance Indicator

    通信中KPI,是Key Performance Indicators的缩写,意思是关键性能指标.performance 还有绩效:业绩的意思,但显然不适用于这种场合. 通信中KPI的内容有:掉话率.接 ...

  4. CodeForces 165C Another Problem on Strings(组合)

    A string is binary, if it consists only of characters "0" and "1". String v is a ...

  5. 模拟赛1031d1

    NP(np)Time Limit:1000ms Memory Limit:64MB题目描述LYK 喜欢研究一些比较困难的问题,比如 np 问题.这次它又遇到一个棘手的 np 问题.问题是这个样子的:有 ...

  6. 火狐的调试利器-----Firebug

    什么是Firebug 从事了数年的Web开发工作,越来越觉得现在对WEB开发有了更高的要求.要写出漂亮的HTML代码:要编写精致的CSS样式表展示每个页面模块:要调试javascript给页面增加一些 ...

  7. poj 算法 分类

    转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6642573 最近AC题:2528   更新时间:2011.09.22  ...

  8. HDOJ-三部曲一(搜索、数学)-1008-Prime Path

    Prime Path Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total S ...

  9. POJ 3308 Paratroopers(最小割EK(邻接表&矩阵))

    Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...

随机推荐

  1. manifest资源提取工具

    因业务需要,写了个manifest资源提取工具,该机制是将html文件作为入口文件进行资源抓取.原理是先简单扫html token,然后直接遍历每个tag token是否属于需要的资源(css,js, ...

  2. 遍历Arraylist的方法:

    遍历Arraylist的几种方法: Iterator it1 = list.iterator();        while(it1.hasNext()){            System.out ...

  3. shell 实现Linux 控制台下树形显示目录

    #!/bin/bash function main(){      local pre=$1    local name=$2    echo "$pre$name"    tes ...

  4. eclipse的插件安装

    如何安装:http://my.oschina.net/linjunlong/blog/126961 插件安装方法:eclipse和myeclipse版本不一样,略有区别 在线安装: 第一种:知道在线安 ...

  5. oracle去重等基础问题

    --去重查询方法一:根据id select * from sxe where id in(select min(id) from sxe group by username) order by id ...

  6. iOS开发小技巧--修改按钮内部图片和文字之间的间距(xib)

    调整按钮的Edge属性,选择调整图片的Edge还是label的Edge,如图:

  7. 【BZOJ 2190】【SDOI 2008】仪仗队 欧拉筛

    欧拉筛模板题 #include<cstdio> using namespace std; const int N=40003; int num=0,prime[N],phi[N]; boo ...

  8. 寻找数组中第K频繁的元素

    问题是:给你一个数组,求解出现次数第K多的元素.当然leetcode上的要求是算法复杂度不能大于O(N*logN). 首先这个问题我先是在leetcode上看到,当时想了两种做法,做到一半都觉得不是很 ...

  9. 卸载移动硬盘出现 device is busy

    umount /dev/sdb1 # device is busy fuser -m -v /dev/sdb1 # 查看 fuser -m -k /dev/sdb1 # 杀死进程

  10. Thinking in java学习笔记之初始化

    1.基本数据类型:类的每个基本数据类型保证有一个初值(char为0输出则是空白) 2.构造器: 3.静态初始化顺序示例及总结 4.非静态初始化顺序 4.数组