3013 单词背诵
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 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;
题解 :
把每一个都hash一下然后直接判断第一问解决;
对于第二问,我们可以贪心地考虑,我们在所选择的区间里有这个字符,那么我们就可以舍弃一个;
于是我们可以每次移动右端点,然后把所有单词找完之后停止,吧左端点往前缩,即如果这个字符串不止出现一次, 我们就可以舍弃他;
然后不一定你选择的第一个区间一定是最优的,所以我们要遍历整个区间;
然后hash取进制数的时候要慎重,我因为这个wa了好几遍;
Code:
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <cstring> 5 #include <map> 6 using namespace std; 7 #define base 26 8 const int mod = 100007; 9 10 int n; 11 long long a[1010]; 12 long long b[100010]; 13 bool hash[100010], vis[100010]; 14 int num[100010]; 15 16 inline int HASH(string x) 17 { 18 int ans = 0; 19 int len = x.length(); 20 for (register int i = 0; i < len; i ++) 21 { 22 ans = (ans * base + x[i]) % mod; 23 } 24 return ans; 25 } 26 27 int ans; 28 int minn = 1e9; 29 30 int main() 31 { 32 scanf("%d", &n); 33 for (register int i = 1; i <= n; ++i) 34 { 35 string s; 36 cin >> s; 37 a[i] = HASH(s); 38 hash[a[i]] = 1; 39 } 40 41 int m;cin >> m; 42 for (register int i = 1 ; i <= m ; i ++) 43 { 44 string s; 45 cin >> s; 46 b[i] = HASH(s); 47 if (hash[b[i]] and !vis[b[i]]) ans++, vis[b[i]] = 1; 48 } 49 cout << ans << endl; 50 51 int r = 1, l = 1; 52 int nn = 0; 53 while (r <= m) 54 { 55 while (r <= m) 56 { 57 if (vis[b[r]] and num[b[r]] == 0) nn ++; 58 num[b[r]]++; 59 r++; 60 if (nn == ans) break; 61 } 62 while ((vis[b[l]] == 0 or num[b[l]] >= 2) and l < r) num[b[l]]--, l++; 63 minn = min(r - l, minn); 64 } 65 66 cout << minn; 67 return 0; 68 }
原文地址:https://www.cnblogs.com/zZh-Brim/p/9245481.html