https://vjudge.net/problem/UVA-129
题目的n是表示第n个出现的串,而不是长度为n的串,所以应该用一个Count全局变量去记录它是第几个,如果一个串符合,那么直接Count++,所用的dfs一定是从'A'开始遍历,所以已经保证了它的字典序最小,我们判断重复只需要判断包含第x个位置的所有偶数串是否重复就可以了,因为前面的串我们之前已经判断过了。
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<cmath> using namespace std; int a[100009]; int s[10009]; int n,L; int Count=0; int dfs(int x)//x代表当前要填的位置 { //printf("x==%d\n",x); int i,j,ok,flag,k; if(Count==n)//边界条件 { for(i=0; i<=x-1; i++) { if(i%64==0&&i!=0) printf("\n"); else if(i%4==0&&i!=0) printf(" "); printf("%c",'A'+s[i]); } printf("\n%d\n",x); return 1; } for(i=0; i<=L-1; i++) { s[x]=i;//当前位置填字母'A'+i; ok=1;//判断x这个位置放'A'+i是不是可以 for(j=1; j<=(x+1)/2; j++) //其实这里的x+1代表了现在的长度 { flag=0; //因为前面已经保证了不重复,所以我们只需要判断 //包含第x个位置的偶数串是否重复就可以了 for(k=0; k<=j-1; k++) { if(s[x-k]!=s[x-k-j]) { //如果找到一个不相等的字符 //在长度为j,包含第x个位置的串是不重复的 flag=1; break; } } if(!flag) //如果flag==0表示有重复 { ok=0; break;//所以无论包含x的串长度是多少都是不符合 } } if(ok) { Count++;//证明这个串是可以的,所以这个串的序号是第Count if(dfs(x+1)) return 1;//return 1 代表找到了 } } return 0;//无论这个位置放什么都不行 //那么由前面推出的这个位置就是错误的 } int main() { int i; while(scanf("%d%d",&n,&L))//n代表第n个出现 L代表可以用多少个字母 { if(n==0&&L==0) break; Count=0; dfs(0); } //printf("%d\n",Count); }