其他分享
首页 > 其他分享> > Codeforces Round #705 (Div. 2) C

Codeforces Round #705 (Div. 2) C

作者:互联网

题目链接

https://codeforces.ml/contest/1493/problem/C

题目截图

 

 

 

 

 

 

题解

  本题解主要是对官方题解的翻译,或者说是自己对官方题解的理解。假设原串为s,答案串为t,并且下标从1开始。首先n%k != 0的情况下t必然不存在!主要步骤分为两大步,第一步是找到答案串和原串的最大公共前缀,第二步是对后缀进行字母分配,理由简单描述如下,第一步中找前缀,很显然答案串比原串的字典序大,且长度相等,那么必然存在公共前缀(若不存在,则前缀长度为0),假设前缀长度len(pref),那么tpref  spref ,否则要么s>t要么pref并不是最长公共前缀,之后就是第二步,既然已经有tpref  spref,那么t>s已经恒成立了,所以只需要将剩余的字母安放并排序即可,这样就能保证t最小且beautiful

 

  · 第一步:找到答案串和原串最大公共前缀

  原串从后往前遍历,用cnt维护目前字母表第i+1 个字母的数目,如cnt1为字母的数目,用sum维护(k - cnti % k) % k的和,表示目前剩余需要增添使得整除k的总字母数(确实有点绕啊,我当时就搞了半天才理解。。。),当sum <= n - i 时,得到最大公共前缀

  · 第二步:为后缀分配字母

  遍历cnt分别增添字母所需数量,得到的串长度不足n的用a补齐(之所以补的a最后依旧能被k整除,是因为k|n,而其余字母数目均被k整除,所以显然a可以),最后对后缀排序即可(其中分界点不参与排序)

cpp code

 

  1 #pragma GCC optimize(2)
  2 #include <bits/stdc++.h>
  3 using namespace std;
  4 #define IOS std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
  5 typedef long long ll;
  6 typedef unsigned long long ull;
  7 const int mod = 1e9 + 7;
  8 const int inf = 0x3f3f3f3f;
  9 struct InputOutputStream {
 10     enum { SIZE = 1000001 };
 11     char ibuf[SIZE], *s, *t, obuf[SIZE], *oh;
 12     bool eof;
 13  
 14     InputOutputStream() : s(), t(), oh(obuf), eof(false) {}
 15     ~InputOutputStream() { fwrite(obuf, 1, oh - obuf, stdout); }
 16  
 17     explicit operator bool() const {
 18         return static_cast<bool>(eof == false);
 19     }
 20  
 21     inline char read() {
 22         if (s == t) t = (s = ibuf) + fread(ibuf, 1, SIZE, stdin);
 23         return s == t ? -1 : *s++;
 24     }
 25  
 26     inline InputOutputStream &operator>>(char* x) {
 27         static char c;
 28         for (c = read(); isspace(c); c = read())
 29             if (c == -1) {eof = true; return *this;}
 30         for (; !isspace(c); c = read()) *x = c, ++x;
 31         *x = 0;
 32         return *this;
 33     }
 34  
 35     template <typename T>
 36     inline InputOutputStream &operator>>(T &x) {
 37         static char c;
 38         static bool iosig;
 39         for (c = read(), iosig = false; !isdigit(c); c = read()) {
 40             if (c == -1) {eof = true; return *this;}
 41             iosig |= c == '-';
 42         }
 43         for (x = 0; isdigit(c); c = read()) x = x * 10 + (c ^ '0');
 44         if (iosig) x = -x;
 45         return *this;
 46     }
 47  
 48     inline void print(char c) {
 49         if (oh == obuf + SIZE) {
 50             fwrite(obuf, 1, SIZE, stdout);
 51             oh = obuf;
 52         }
 53         *oh++ = c;
 54     }
 55  
 56     template <typename T>
 57     inline void print(T x) {
 58         static int buf[23], cnt;
 59         if (x != 0) {
 60             if (x < 0) print('-'), x = -x;
 61             for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
 62             while (cnt) print((char)buf[cnt--]);
 63         } else print('0');
 64     }
 65  
 66     template <typename T>
 67     inline InputOutputStream &operator<<(const T &x) {
 68         print(x);
 69         return *this;
 70     }
 71  
 72     inline void print(const char* x) {
 73         for(; *x; x++)
 74             print(*x);
 75     }
 76 
 77     inline void print(char* x) {
 78         for(; *x; x++)
 79             print(*x);
 80     }    
 81 } io;
 82 
 83 const int maxn = 1e5 + 50;
 84 
 85 int t, n, k;
 86 char s[maxn];
 87 int cnt[26];
 88 int sum = 0;
 89 char res[maxn];
 90 
 91 inline int get_cnt(int x) {
 92     return (k - x % k) % k;
 93 }
 94 
 95 signed main() {
 96     io >> t;
 97     while(t--) {
 98         sum = 0;
 99         memset(cnt, 0, sizeof(cnt));
100         memset(res, 0, sizeof(res));
101         io >> n >> k;
102         io >> (s + 1);
103         for(int i = 1;i <= n;++i) { cnt[s[i]-'a']++; }
104         for(int i = 0;i < 26;++i) {
105             sum += get_cnt(cnt[i]);
106         }
107         if(sum == 0) {
108             io << (s + 1) << '\n';
109             continue;
110         } 
111         if(n % k != 0) {
112             io << "-1\n";
113             continue;
114         }
115         for(int i = n;i >= 1;--i) {
116             bool flag = false;
117             sum -= get_cnt(cnt[s[i]-'a']);
118             cnt[s[i]-'a']--;
119             sum += get_cnt(cnt[s[i]-'a']);
120             for(int j = s[i] - 'a' + 1;j < 26;++j) {
121                 int lst_sum = sum;
122                 sum -= get_cnt(cnt[j]);
123                 cnt[j]++;
124                 sum += get_cnt(cnt[j]);
125 
126                 if(sum <= n - i) {
127                     for(int p = 1;p <= i - 1;++p) {
128                         res[p] = s[p];
129                     }
130                     res[i] = 'a' + j;
131                     int tot = i;
132                     for(int w = 0;w < 26;++w) {
133                         int f = get_cnt(cnt[w]);
134                         while(f--) { res[++tot] = w + 'a'; }
135                     }
136                     while(tot < n) { res[++tot] = 'a'; }
137                     sort(res + 1 + i, res + 1 + n);
138                     io << (res + 1) << '\n';
139                     flag = true;
140                     break;
141                 }
142 
143                 sum = lst_sum;
144                 cnt[j]--;
145             }
146             if(flag) { break; }
147         }
148     }        
149     return 0;
150 }
View Code

 

标签:cnt,前缀,read,705,sum,Codeforces,char,Div,obuf
来源: https://www.cnblogs.com/mfsyflt/p/14508024.html