[CODEVS3031] 单词背诵 - 字符串hash

Posted zzh-brim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CODEVS3031] 单词背诵 - 字符串hash相关的知识,希望对你有一定的参考价值。

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 }

 

 

 

以上是关于[CODEVS3031] 单词背诵 - 字符串hash的主要内容,如果未能解决你的问题,请参考以下文章

单词背诵CodeVS3013 哈希

codevs 3013 单词背诵 hash

CODEVS——T 3013 单词背诵

codevs3031最富有的人[字典树]

codevs 3031:最富有的人

单词背诵