对于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 }