CF 1083 B. The Fair Nut and Strings

B. The Fair Nut and Strings 

题目链接

题意:

  在给定的字符串a和字符串b中找到最多k个字符串,使得不同的前缀字符串的数量最多。

分析:

   建出trie树,给定的两个字符串就是trie树上的两条长度为n路径,那么就是在第n层的所有节点中,找到不大于k个点,(第n层的每个点向上到根的路径的路径上的字符组成一个长度为n字符串)。

  两个第n层的节点一共会构成2n-lca个不同的前缀。所有可以根据这个贪心的选。每次尽量选已经走过的路径尽量少的路径。 

  从n往后枚举,计算长度为答案为i的可以选几个。

  注意判断一下最后是否可以选择k个, 和已经选了的路径。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #define fi(s) freopen(s,"r",stdin)
12 #define fo(s) freopen(s,"w",stdout)
13 using namespace std;
14 typedef long long LL;
15 
16 inline int read() {
17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
19 }
20 
21 const int N = 1000005;
22 char a[N], b[N];
23 
24 int main () {
25     int n = read(); LL k; cin >> k;
26     scanf("%s%s", a + 1, b + 1);
27      
28     LL now = 1, ans = 0, tot = 0;
29     
30     for (int i = 1; i <= n; ++i) {
31         now = now * 2;
32         if (a[i] == 'b') now --;
33         if (b[i] == 'a') now --;
34         if (now >= k) { tot = k; break; }
35     }
36     if (tot == 0) tot = now;
37     
38     now = 1;LL last = 0;
39     for (int i = 1; i <= n; ++i) {
40         now = 1ll * now * 2;
41         if (a[i] == 'b') now --;
42         if (b[i] == 'a') now --;
43         LL t = min(k, now); t = min(t, tot); t = min(t, now - last); t = max(t, 0ll);
44         ans += 1ll * t * (n - i + 1);
45         k -= t; tot -= t; last += t;
46         if ((!k) || (!tot)) break;
47     }
48     cout << ans;
49     return 0;
50 }

 

posted @ 2018-12-11 09:41  MJT12044  阅读(754)  评论(0编辑  收藏  举报