zzuliOJ 1912:小火山的爱情密码(尺取法||二分)

1912: 小火山的爱情密码

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 278   Solved: 81

Submit Status Web 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
2a 
2n
2c

Sample Output

6

HINT

Source

zzuli

解题思路:尺取法设置左右区间,如果该区间符合要求那么抛弃左端点,看是否符合要求,不符合要求则右区间+1,,再判断。。。(每次符合要求时更新下ans);这道题二分也能做,有些繁琐吧应该。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
int need[30];
int have[30];
bool judge()//判断该区间是否符合题意 
{
	for(int i=0;i<26;i++)
	{
		if(have[i]<need[i])//一旦某个字母不合题意,那么肯定整体不合题意 
		return false;
	}
	return true;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(need,0,sizeof(need));
		memset(have,0,sizeof(have));
		int n,k;
		char s[10010];
		scanf("%d%d",&n,&k);
		scanf("%s",s);
		char word;
		int num;
		for(int i=0;i<k;i++)
		{
			getchar();
			scanf("%c %d",&word,&num);
			need[word-'a']=num;//储存需要的字母个数们 
		}
		int l=0;//初始化区间左端点 
		int ans=INF;//初始化答案 
		for(int r=0;r<n;r++)
		{
			have[s[r]-'a']++;//每扩大右区间时别忘了将新点的字母加上去 
			while(judge())//注意用while 
			{
				ans=min(ans,r-l+1);//更新ans 
				have[s[l]-'a']--;//符合题意,刨除左端点,那么左端点的字母就不算了 
				l++;//左端点扩张 
			}
		}
		if(ans==INF)//还是初始化时的答案,说明不合题意,输出-1 
		{
			printf("-1\n");
		}
		else
		{
			printf("%d\n",ans);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值