时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个只包含小写字母‘a‘-‘z‘的字符串 S ,你需要将 S 中的字符重新排序,使得任意两个相同的字符不连在一起。
如果有多个重排后字符串满足条件,输出字典序最小的一个。
如果不存在满足条件的字符串,输出INVALID。
输入
字符串S。(1 ≤ |S| ≤ 100000)
输出
输出字典序最小的答案或者INVALID。
- 样例输入
-
aaabc
- 样例输出
-
abaca
- Solution:
- 不难看出这题解法是贪心,也不难看出INVALID的充要条件是
- $存在字母i\text{ s.t. }\ i在字符串s中出现的次数cnt[i]>\lceil\frac{i}{2}\rceil.$
- 但是容易忽略的一点是:
- 如果字符串s是VALID的,不能直接无脑贪心,而要试探:
- $在当前位置放置某字符后,剩下的字符是否还是\text{VALID}的,如果不是,就不能放置.$
- 我在这个点上WA了3发,最后用这个数据
- $\texttt{abcabc}$
- 找到了bug.
- 我代码输出
- $\texttt{ababc}$
- 显然是错的,应当输出
- $\texttt{abacbc}$.
- Implementation:
-
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N(1<<17); 5 6 char s[N]; 7 int cnt[26]; 8 9 bool valid(int x){ 10 for(int i=0; i<26; i++) 11 if(cnt[i]>(x-1)/2+1) 12 return false; 13 return true; 14 } 15 16 int main(){ 17 cin>>s; 18 int n=0; 19 for(; s[n]; n++) 20 cnt[s[n]-‘a‘]++; 21 if(!valid(n)) puts("INVALID"); 22 else{ 23 int pre=-1; 24 for(int i=0; s[i]; i++){ 25 for(int j=0; j<26; j++) 26 if(cnt[j] && j!=pre){ 27 cnt[j]--; 28 if(valid(n-1)){ 29 putchar(‘a‘+j), pre=j, n--; 30 break; 31 } 32 else cnt[j]++; 33 } 34 } 35 puts(""); 36 } 37 }
-
- conclusion:
到处都是坑,静态差错查不出时,一定要出几组数据试试,往往能很快找到反例.
时间: 2024-10-12 08:01:23