->题目单击这<-
题目大意:跟2610基本一样,就不多说了,唯一的区别是输出部分,2610输出要求按子串中数字出现的位置靠前的先输出,本题则要求按子串的逻辑顺序输出,即先输出短的,长度相同的子串按第一个不相同的数的大小升序输出。2610按出现的位置输出,直接在原串上搜索就可以了,先搜到的一定是位置靠前的。但本题要求从小到大输出,所以很容易想到要对原数组排序,在排好序的数组里面搜,结果就一定满足输出要求,因为排完序后先搜到的一定是小的。但是这样会出现问题,因为排完序后会搜到许多错误的子串,在原串中不满足要求的,一排序就能满足不递减了,所以2610的2个判重也是要加上的,最后判断一下,搜到的子串在原数组中的下标是否也是递增的,如果是就是合法的,输出之,否则不合法,弃之。本题还需要注意的问题是第二种判重(见2610题解),在判重的时候不能在排好序的数组中判重,应该在原数组中遍历,看是否已经出现过当前数字,因为你在排好序的数组中这样判重的话,会把一些合法的答案弃掉了。
比如原序列1 2 3 2 3 排好序后是1 2 2 3 3,现在搜长度为4的子串,已搜1 2 2 ,现在搜第四个3,发现第四个数3在原数组中的位置是3 < 第3个数2在原数组中的位置4,不合法,弃之,然后搜第5个3,现在执行第二种判重,如果在排好序的数组中判重的话,就会发现第四个位置有了3,于是也会放弃这组,而实际情况是,1 2 2 3 是合法的!所以要在第三个2在原数组的位置4开始,到第五个数3在原数组的位置5之间看有没有3出现,显然是没有的,所以1 2 2 3 合法。
这样把2610的代码稍做改动就可以过这个题了,基本一样的。详情请见代码:
#include <iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct node { int id,num; }lcm[105]; int n,p; int yuan[105]; int flag; bool flag1[10000005]; int ans[105]; //int first[105],firstnum; int cmp(struct node a,struct node b) { if(a.num != b.num)//此处WA了数次!!! return a.num < b.num; else return a.id < b.id; } /*int appear(int t) { int i; for(i = 0;i < firstnum;i ++) if(first[i] == t) return 1; return 0; } */ int isok(int s,int cp) { if(s > cp) return 0; int i; for(i = s + 1;i < cp;i ++) if(yuan[i] == yuan[cp]) return 0; return 1; } void dfs(int cur,int deep,int curdeep) { int ii; if(p <= 0) return; if(curdeep == deep) { for(ii = 2;ii <= deep;ii ++) if(lcm[ans[ii]].id < lcm[ans[ii - 1]].id) return; p --; flag = 1; for(ii = 1;ii < deep;ii ++) printf("%d ",lcm[ans[ii]].num); printf("%d\n",lcm[ans[ii]].num); return; } for(ii = cur + 1;ii <= n;ii ++) { if(lcm[ii].id < lcm[cur].id) continue; if(isok(lcm[ans[curdeep]].id,lcm[ii].id)) { ans[curdeep + 1] = ii; dfs(ii,deep,curdeep + 1); } } } int main() { int i,j; while(scanf("%d%d",&n,&p) != EOF) { for(i = 1;i <= n;i ++) { scanf("%d",&lcm[i].num); yuan[i] = lcm[i].num; lcm[i].id = i; } flag = 1; sort(lcm + 1,lcm + 1 + n,cmp); for(i = 1;i <= n && flag;i ++)//搜索深度 { flag = 0;// memset(flag1,0,sizeof(flag1)); //firstnum = 0; for(j = 1;j <= n;j ++) { if(flag1[lcm[j].num] == 0)//!appear(lcm[j].num))//lcm[i].num != lcm[i - 1].num)//) { //first[firstnum ++] = lcm[j].num; flag1[lcm[j].num] = 1; ans[1] = j; dfs(j,i,1); } } } printf("\n"); } return 0; } //187MS 336K /* 3 5 1 3 2 3 6 1 3 2 4 100 1 2 3 2 5 20 1 2 3 2 3 5 20 1 2 3 4 2 5 4 1 2 3 2 3 5 10 1 2 3 4 5 5 10 5 4 3 2 1 */PS:本题改完后提交各种哇,后来在sort函数的cmp函数里面把下标比较加上才过了,还是因为不了解STL函数的内部机制,不知道cmp函数是如何工作的,原以为直接对内容排序即可,排完序的序列下标应该是递增的,此题说明并非如此,如有大牛路过,还请不吝赐教,弱菜感激不尽。