1912: 小火山的爱情密码
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 185 Solved: 47
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
16 3cancanc 2a 2n 2
Sample Output
6
HINT
Source
题解:灵活变化一下,还是尺取法,想明白就好了,但是就是不愿意想,这不行啊!!!还有要会变通啊!
开一个数组 need[27] 记录需要的字母及每个个数,一个 for 循环,依次记录每个字母出现的次数 have[27] ,同时与 need[27] 中相同字母比较,满足条件记录 ans ( ans = min( ans , i-st+1)) ,然后右端点不动,左端点右移缩小 ans,直到不满足条件。右端点右移......
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ix(x) (x-'a')
#define INF 0x3f3f3f3f
#define CLR(a,b) memset(a,b,sizeof(a))
int need[27];
int have[27];
bool check()
{
for(int i=0;i<26;i++)
{
if(have[i]<need[i])
return false;
}
return true;
}
int main()
{
int u;
scanf("%d",&u);
while(u--)
{
CLR(need,0);
CLR(have,0);
int n,m;
char s[10010];
scanf("%d %d",&n,&m);
scanf("%s",s);
for(int i=1;i<=m;i++)
{
char c[5];
int num;
scanf("%s %d",c,&num);
need[c[0]-'a']=num; //记录每个字符要求出现的数量
}
int st=0;
int ans=INF;
for(int i=0;i<n;i++)
{
int t=ix(s[i]);
have[t]++; //记录有的字符的数量
if(check()) //检查
{
while(check())
{
ans=min(ans,i-st+1); //更新 ans
int t1=ix(s[st]);
have[t1]--; //左端点要右移,左端点字符数目-1
st++; //左端点右移
}
}
}
if(ans==INF)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}