题解 P2724 【联系 Contact】

「QQ红包」

2016-08-02 14:01:57

Solution

题解by:redbag 百度了很多题解,都有写到输出很坑。 然而我想说的是 ###**输出太坑了。** usaco对格式要求太严格了。 0. 输出完频率要换行。 0. 输出6个序列要换行。 0. 输出完序列要换行。 0. 如果该频率的序列刚好是6个的话只要换一次行。 0. 每行第一个序列之前不能有空格。 0. 每行最后一个序列之后不能有空格。 关于排序 0. 频率高的在前。 0. 频率一样时,位数少的在前。 0. 位数也一样时,字典序小的在前。 存的话用map来存每个序列对应的编号。 x[i/\*i为标号\*/].s存这个序列,x[i].a存频率。 然后才能不愉快的AC。 ```cpp /* ID: ylx14271 PROG: contact LANG: C++ */ #include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<math.h> #include<time.h> #include<vector> #include<bitset> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> #define LL unsigned long long using namespace std; map<string,int> s; int a,b,n,i,j,k,len,ls,xx; char ch; char c[5000000]; struct haha { string s; int a; }x[100100]; int cmp(haha aa,haha bb) { if (aa.a>bb.a) return 1;//频率从小到大排序 if (aa.a==bb.a)//频率相等 { if (aa.s.size()<bb.s.size())return 1;//长度短的在前 if (aa.s.size()==bb.s.size()&&aa.s<bb.s)return 1;//字典序小的在前 return 0; } return 0; } int main() { freopen("contact.in","r",stdin); freopen("contact.out","w",stdout); scanf("%d %d %d\n",&a,&b,&n); while ((ch=getchar())!=EOF)//读入 { if (ch=='1'||ch=='0') { len++;//len:统计位数的 c[len]=ch;//存起来 //len作为某个串的结尾,枚举开头 string ss=""; int B=max(len+1-b,1);//一定要比1大 for (i=len;i>=B;i--) { ss=c[i]+ss;//要加在前面,我就不用substr if (len-i+1>=a)//长度>=a { if (s[ss]==0)//从未出现 { ls++; s[ss]=ls;//标记 x[s[ss]].s=ss;//储存 } x[s[ss]].a++;//统计 } } } }//尼玛要怎么输出啊 (╯▽╰),好坑 sort(x+1,x+ls+1,cmp);//从大到小排序 for (i=1;i<=ls;i++) {//N个频率最高的序列要全部输出完才能退出 if (n==0&&x[i].a!=x[i-1].a) break; if (x[i].a==x[i-1].a)//和上一个出现次数一样 { if (xx%6==0) cout<<x[i].s;//每一行的开头不要加空格 else cout<<" "<<x[i].s;//否则就要加空格 xx++; if (xx%6==0) printf("\n");//6个一换行 } else { n--;//又输出了一个出现频率 if (i!=1&&xx%6!=0) printf("\n"); //出现之前那个频率的串,如果是6的倍数,结尾就换行了,在此就不用再换行了。 printf("%d\n",x[i].a);//输出完频率之后换行 cout<<x[i].s;//再输出串 xx=1;//重新统计 } } if (xx%6!=0) printf("\n");//如果最后一个数有6个的话, return 0; }```