您的位置:首页 > 其它

hdu-5672 String(尺取法)

2016-04-22 22:40 330 查看
题目链接:
String

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

问题描述
有一个 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

思路:

尺取法找左边界;比赛最后MLE了,一开始是直接把每个位置的状态都记下来,还是一边更新边界一边更新字母的数目比较好;哎;

AC代码:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1e6+6;
char s
;
int num1[30],num2[30];
int k;
int check()
{
int ans=0;
for(int i=0;i<26;i++)
{
if(num1[i]-num2[i]>0)
{
ans++;
}
}
if(ans>=k)return 1;
return 0;
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
scanf("%d",&k);
int len=strlen(s);
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
int l=1,r=len+1;
num1[s[0]-'a']++;
ll ans=0;
for(int i=1;i<=len;i++)
{
while(l<=len&&!check())
{
l++;
if(l<=len)num1[s[l-1]-'a']++;
}
num2[s[i-1]-'a']++;
ans+=(ll)(r-l);
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: