51Nod - 1255

  也是第十一届校赛的C题,不过他把1e5改成了1e7.

  一开始就想到用贪心做。思路是这样的:开一个字符数组ans保存答案。然后从头到尾遍历题目给出的字符串S,如果ans数组中还没有这个字母,那么就把字母加到ans尾部。如果已经有这个字母了,那么就看ans中这个字母a后面的一个字母b,如果a>b,那么就把a去掉,a后面的字母依次向前一位,然后在ans的尾部加入与a一样的那个字母。后来发现,这个思路是错误的,如果是类似 “egaeg” 这样的字符串,那么这种思路明显无法找到答案。

  后来,在f_zyj的题解(http://blog.csdn.net/f_zyj/article/details/52355698)的点拨下,用新的思路:开一个字符数组ans保存答案。然后从头到尾遍历题目给出的字符串S,如果ans数组中还没有这个字母,那么就把字母加到ans尾部。如果已经有这个字母(设为a)了,那么继续遍历a后面的字母,发现某个字母c<a而且c和a之间的所有字母都大于a并且在后面的S中还有得替换,那么就把a去掉,a后面的字母依次向前一位,然后在ans的尾部加入与a一样的那个字母。

  AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 const int maxn=1e7+5;
 5 char ch[maxn];
 6 int numch[30];
 7 int vis[30];
 8 char ans[30];
 9 int main(){
10     int now=1;
11     scanf("%s",ch);
12     
13     int len=strlen(ch);
14     
15     for(int i=0;i<len;i++)
16         numch[ch[i]-'a']++;
17         
18     for(int i=0;i<len;i++){
19         numch[ch[i]-'a']--;
20         if(vis[ch[i]-'a']==0){
21             ans[now]=ch[i];
22             vis[ch[i]-'a']=1;
23             now++;
24             continue;
25         }
26         
27         for(int m=1;m<now;m++){
28             if(ans[m]==ch[i]){
29                 for(int n=m+1;n<now;n++){
30                     if(numch[ans[n]-'a']==0&&ans[n]>ans[m])  break;
31                     if(ans[n]<ans[m]){
32                         for(int k=m;k<now-1;k++)
33                             ans[k]=ans[k+1];
34                         ans[now-1]=ch[i];
35                         break;
36                     }
37                 }
38                 break;
39             }
40         }
41     }
42     printf("%s\n",ans+1);
43     return 0;
44 }
View Code

  这里还有一个小插曲。一开始我并没有用 “int len=strlen(ch);” 把strlen(ch)的结果记起来,而是用了两次strlen(),结果就超时了。。。以后要把strlen()当作一个for循环来看待,不能小看它的运行时间!

posted @ 2017-05-28 13:36  Blogggggg  阅读(330)  评论(0编辑  收藏  举报