洛谷P1381单词背诵

单词背诵

题目描述

灵梦有 \(n\) 个单词想要背,但她想通过一篇文章中的一段来记住这些单词。

文章由 \(m\) 个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。

输入格式

\(1\) 行一个数 \(n\),接下来 \(n\) 行每行是一个长度不超过 \(10\) 的字符串,表示一个要背的单词。

接着是一个数 \(m\),然后是 \(m\) 行长度不超过 \(10\) 的字符串,每个表示文章中的一个单词。

输出格式

输出文件共 \(2\) 行。第 \(1\) 行为文章中最多包含的要背的单词数,第 \(2\) 行表示在文章中包含最多要背单词的最短的连续段的长度。

样例 #1

样例输入 #1

3
hot
dog
milk
5
hot
dog
dog
milk
hot

样例输出 #1

3
3

提示

数据规模与约定

  • 对于 \(30\%\) 的数据,\(n \le 50\)\(m \le 500\)
  • 对于 \(60\%\) 的数据,\(n \le 300\)\(m \le 5000\)
  • 对于 \(100\%\) 的数据,\(n \le 1000\)\(m \le 10^5\)

代码:

#include<iostream>
#include<map>
using namespace std;
string s[100005], s1;
int n, m;
map<string, bool> word;
map<string, int> cnt;
int sum, len;
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s1; word[s1] = 1;
	}
	//输入s数组
	cin >> m;
	for (int i = 1; i <= m; i++) cin >> s[i];

	//使用双指针进行遍历
	for (int i = 1, j = 1; j <= m; j++) {
		if (word[s[j]]) cnt[s[j]]++;
		if (cnt[s[j]] == 1) sum++, len = j - i + 1;
		while (i <= j) {
			if (cnt[s[i]] == 1) break;
			if (cnt[s[i]] > 1) cnt[s[i]]--, i++;
			if (!word[s[i]]) i++;
		}
		len = min(len, j - i + 1);
	}
	cout << sum << endl << len << endl;
	return 0;
}
posted @ 2024-10-14 21:28  名称无法显示  阅读(3)  评论(0编辑  收藏  举报