CODEVS3013 单词背诵 【Hash】【MAP】
CODEVS3013 单词背诵
题目描述 Description
灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词。
文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。
输入描述 Input Description
第1行一个数n,
接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。
接着是一个数m,
然后是m行长度不超过10的字符串,每个表示文章中的一个单词。
输出描述 Output Description
输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度
样例输入 Sample Input
3
hot
dog
milk
5
hot
dog
dog
milk
hot
样例输出 Sample Output
3
3
数据范围及提示 Data Size & Hint
对于30%的数据 n<=50,m<=500;
对于60%的数据 n<=300,m<=5000;
对于100%的数据 n<=1000,m<=100000;
用map水一水hash,双指针记录一下就好了,特判一下结果为0的情况
#include<bits/stdc++.h>
using namespace std;
#define N 100010
map<string,int> mp;
string s;
int t[N],a[N],vis[N],vis1[N]={0};
int n,m,ans1=0,ans2=N;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>s;
mp[s]=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
cin>>s;
if(mp.count(s)){
t[i]=mp[s];
vis[t[i]]=1;
}else t[i]=0;
}
for(int i=1;i<=n;i++)ans1+=vis[i];
if(ans1==0){
printf("0\n0");
return 0;
}
printf("%d\n",ans1);
int l=1,r=0,count=0;
while(1){
while(!t[++r]&&r<=m);
if(r>m)break;
if(!vis1[t[r]])count++;
vis1[t[r]]++;
while(l<r&&(!t[l]||vis1[t[l]]>1)){
if(!t[l]){l++;continue;}
vis1[t[l]]--;
l++;
}
if(count==ans1)ans2=min(ans2,r-l+1);
}
printf("%d",ans2);
return 0;
}