51Nod - 1255

Posted Blogggggg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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循环来看待,不能小看它的运行时间!

以上是关于51Nod - 1255的主要内容,如果未能解决你的问题,请参考以下文章

51Nod - 1255

51nod 1255 字典序最小的子序列

C - 字典序最小的子序列 51nod1255

51Nod1255 字典序最小的子序列

51nod1563

51Nod1039 N^3 Mod P 数论 原根 BSGS