1912: 小火山的爱情密码
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 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
解题思路:尺取法设置左右区间,如果该区间符合要求那么抛弃左端点,看是否符合要求,不符合要求则右区间+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;
}