hihocoder #1327

传送门

时间限制: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:

到处都是坑,静态差错查不出时,一定要出几组数据试试,往往能很快找到反例.

 



posted @ 2016-07-15 01:48  Pat  阅读(531)  评论(0编辑  收藏  举报