您的位置:首页 > 其它

Zzuli OJ-----1912 小火山的爱情密码

2016-08-11 10:36 393 查看

1912: 小火山的爱情密码

Time Limit: 1 Sec Memory Limit:
128 MB

Submit: 212 Solved: 56

SubmitStatusWeb
Board

Description

小火山获得了一个字符串,然而大火山让小火山从里面截取一段字符串,并且让小火山截取的字符串满足一些字符达到一定数量。
小火山觉得很容易,但是他想要知道他至少得截取多长的字符串。

Input

首先是一个整数t(t<=100),表示测试数据组数。接下来是两个整数n和m(n<=10000, m<=10),n表示字符串的长度,m表示要满足一定数量的字符
的种类.(字符只包含小写英文字母)
个数(没有重复字符种类),然后有m行,每行第一个是一个字符,然后是一个整数x(x<=50),表示这种字符的的要求数量。

Output

输出最小长度,如果达不到要求输出-1

Sample Input

1

6 3

cancan

c 2

a 2

n 2

Sample Output

6

二分,和青蛙跳石头思路差不多,开始只标记了m个字母,结果WA,感觉思路没错,就是过不去,最后还是标记了26个字母才过去

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10010
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
char s[maxn];
int num[maxn], dis[maxn][50], sum[maxn];
int m, n, ans;
bool judge(int mid){
for(int i = 0; i <= n-mid; i++){
int ok = 1;
for(int k = 0; k < 26; k++){
if(dis[i+mid][k]-dis[i][k] < num[k]){
ok = 0;
break;
}
}
if(ok){
return true;
}
}
return false;
}
int main(){
int t, d, c;
char ch;
scanf("%d", &t);
while(t--){
ans = 0;
memset(dis, 0, sizeof(dis));
memset(num, 0, sizeof(num));
memset(sum, 0, sizeof(sum));
scanf("%d%d", &n, &m);
scanf(" %s", s+1);
for(int i = 0; i < m; i++){
scanf(" %c%d", &ch, &d);
c = ch-97;
num[c] = d;
}
for(int i = 1; i <= n; i++){
c = s[i]-97;
sum[c]++;
for(int j = 0; j < 26; j++){
dis[i][j] = sum[j];
}
}
int l, r, mid, flag;
l = 0;
r = mid = n;
flag = n+1;
while(l <= r){
if(judge(mid)){
flag = min(flag, mid);
r = mid-1;
}
else{
l = mid+1;
}
mid = (l+r) >> 1;
}
if(flag > n){
printf("-1\n");
continue;
}
printf("%d\n", flag);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: