单词背诵
题目描述
灵梦有 n n n 个单词想要背,但她想通过一篇文章中的一段来记住这些单词。
文章由 m m m 个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。
输入格式
第 1 1 1 行一个数 n n n,接下来 n n n 行每行是一个长度不超过 10 10 10 的字符串,表示一个要背的单词。
接着是一个数 m m m,然后是 m m m 行长度不超过 10 10 10 的字符串,每个表示文章中的一个单词。
输出格式
输出文件共 2 2 2 行。第 1 1 1 行为文章中最多包含的要背的单词数,第 2 2 2 行表示在文章中包含最多要背单词的最短的连续段的长度。
样例 #1
样例输入 #1
3
hot
dog
milk
5
hot
dog
dog
milk
hot
样例输出 #1
3
3
提示
数据规模与约定
- 对于 30 % 30\% 30% 的数据, n ≤ 50 n \le 50 n≤50, m ≤ 500 m \le 500 m≤500;
- 对于 60 % 60\% 60% 的数据, n ≤ 300 n \le 300 n≤300, m ≤ 5000 m \le 5000 m≤5000;
- 对于 100 % 100\% 100% 的数据, n ≤ 1000 n \le 1000 n≤1000, m ≤ 1 0 5 m \le 10^5 m≤105。
思路
第一问很简单,我们可以直接用map集合来存储单词,但单词的出现的个数为1,就让答案++。
第二问:要求文章中包含最多要背单词的最短的连续段的长度,这句话的意思就是说寻找某长度的段落包含之前背过的单词数量,那么我们可以用 l l l来表示连续长度的上端点。
我们什么时候 l l l要++呢?
- 情况1:当同一个单词出现了两次,那么l++,并将此时的单词数–。
- 情况2:当不存在此单词,l++。
总结:对于连续性的题目,我们均采取类似双指针的写法(也就是对一连续区间进行分析)
代码
//直接用map映射
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int N = 1e5+10;
map<string,int>s,f;
int n,m;
string a[N];
int main(){
cin>>n;
int minv=2e9;
for(int i=1;i<=n;i++){
string b;
cin>>b;
// s[a]++;
f[b]++;
}
cin>>m;
int ans1=0,ans2=0;
int cnt=0;
int l=1;
for(int i=1;i<=m;i++){
cin>>a[i];
if(f[a[i]])s[a[i]]++;
if(s[a[i]]==1)ans1++,ans2=i-l+1;
while(l<=i){
if(!f[a[l]]){
l++;
continue;
}
if(s[a[l]]>=2){
s[a[l]]--;
l++;
continue;
}
break;
}
ans2=min(ans2,i-l+1);
}
cout<<ans1<<endl<<ans2;
return 0;
}