/* 问题描述:如果一个字符串包含两个相邻的重复子串,则称它为"容易的串",其他称为"困难的串".
* 例如,BB、ABCDACABCAB都是容易的,而D、DC、ABDAB都是困难的
* 输入正整数n和L,输出由前L个字符组成的、字典序第n小的困难串 .假设输入字符不超过80个
* 例如:L=3时,前7个困难串分别是:A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA
* 思路:从左至右依次考虑每个位置上的字符。判断当前字符串是否存在连续的重复子串。
* 一种方法时判断所有的偶数长度的子串是否存在连续的重复字串,但是这样的重复工作太多效率太低
* 如果我们每添加一个字符都判断一下包含新字符的子串与前面的串是否有冲突,那么仅考虑当前的串即可,
* 因为在新字符添加之前的串已经检查过,就减少了很多工作量
* */
import java.util.Scanner;
public class HardString {
static final int MAXN = 85;
static int[] s = new int[MAXN];
static int count = 0;
static int n, l;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while ((n = scanner.nextInt()) > 0) {
l = scanner.nextInt();
count = 0;
dfs(0);
}
}
private static int dfs(int cur) {// 返回0表示已经得到解
if (count++ == n) {
for (int i = 0; i < cur; i++)
System.out.printf("%c", 'A' + s[i]);
System.out.println();
return 0;
}
for (int i = 0; i < l; i++) {
s[cur] = i;
int ok = 1;
for (int j = 1; j * 2 <= cur + 1; j++) {// 尝试长度为j*2的后缀
boolean equal = true;
for (int k = 0; k < j; k++) {// 检查后一半是否等于前一半
if (s[cur - k] != s[cur - k - j]) {
equal = false;
break;
}
}
if (equal) {// 后一半等于前一半 方案不合法
ok = 0;
break;
}
}
if (ok == 1) {// 合法
if (dfs(cur + 1) == 0)// 递归搜索 找到解直接退出
return 0;
}
}
return 1;
}
}
困难的串
最新推荐文章于 2022-02-25 10:35:45 发布