您的位置:首页 > 其它

【zzuli-ij】-1912: 小火山的爱情密码(尺取法,好)

2016-08-11 08:51 344 查看

1912: 小火山的爱情密码

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 185  Solved: 47

SubmitStatusWeb
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: