题目描述
将一个包含两个相邻的重复子串的子串,称为“容易的串”,其他为“困难的串”。 输入正整数n和l,输出由前l个字符组成的,字典序第k小的困难的串。
输入样例
7 3
30 3
0 0
输出样例
7 3
ABAC ABA
7
30 3
ABAC ABCA CBAB CABA CABC ACBA CABA
28
0 0
思路解析: 这个题是求字符串的困难串,在进行判断时,由于困难串比较难判断,我们来判断简单串,如果判断简单串呢?我们只需要判断字符串的后缀子串即可.因为一个困难串+一个字符,相邻子串只可能出现在后面.所以我们只需要判断后缀即可.
之后采用DFS解决即可.
参考代码
#include<iostream>
using namespace std;
int n,cnt,L,S[100];
int dfs(int cur){
//判断困难串是否达到了n
if(cnt++==n){
for(int i = 0; i < cur; i++){
if(i&&i%4==0&&i!=64){
cout<<" ";
}else if(i==64){
cout<<endl;
}
cout<<char('A'+S[i]);
}
cout<<endl;
cout<<cur<<endl;
return 0;//结束
}
for(int i = 0;i < L;i++)//依次判断cur位置可能出现的字符.
{
S[cur] = i;
int ok = 1;//困难串的标记
for(int j = 1; j*2 <= cur+1; j++) {//判断所有的后缀
int equal = 1;
for(int k = 0; k < j;k++){
if(S[cur-k]!=S[cur-k-j]){//不相等,说明以J*2为后缀不是简单串 (但该字符串未必就是困难串,因为还有其他后缀,只有所有后缀都遍历过且都不是简单串 才成立. )
equal = 0;
break;
}
}
if(equal){//equal:0 困难串 equal:1简单串 如果是简单串则结束该字符串,进行开始尝试下一个字符串.
ok = 0;
break;
}
}
if(ok){
if(!dfs(cur+1)){//如果是困难串,则进行继续深搜.当返回后判断是否已经找够,如果找够了,则结束该层dfs. 没找够则继续往后寻找
return 0;
}
}
}
return 1;
}
int main()
{
while(scanf("%d %d",&n,&L)!=EOF &&n &&L){
cnt = 0;
dfs(0);
}
return 0;
}