1. 问题描述:
如果一个字符串包含两个相邻的重复子串,则称它为容易的串,其他串称为困难的串
如:BB,ABCDACABCAB,ABCDABCD都是容易的,A, AB, ABA, D, DC, ABDAB, CBABCBA都是困难的。
输入正整数n, L 输出由前L个字符(大写英文字母)组成的,字典序第n小的困难的串。
例如,当L=3时,前7个困难的串分别为:
A, AB, ABA, ABAC, ABACA, ABACAB, ABACABA
n指定为4的话,输出ABAC
2. 因为是要进行试探的结果那么我们这里使用dfs来进行解决,其中这道题目涉及到两个难点,一是维持字典序的问题,另外一个是如何判断是否为困难的串的问题
①维持字典序的话我们能够尽量往深的地方搜索,就尽量往深的地方搜索,而尽量不去搜索它的横的地方,即能不搜索它的兄弟尽量不搜索它的兄弟
所以这里当把当前的字符加进来的时候,就永远不会退回去去搜索它的平行状态即不搜索它的兄弟元素了,就没有了平行状态了,所以此时就不需要进行回溯了,因为它不受到平行状态的影响了
②二是要解决如何判断是否为困难的串的问题,这里使用到了一种技巧就是不用去搜索它的所有的情况,即不用相邻一个一个进行判断,相邻两个两个字符进行判断...我们考虑到这里传进方法来的本来就是一个困难的串,所以并不需要像上面这样进行搜索情况的判断,只需要考虑当前加入的字符与其他字符组合起来再与相邻长度的字符串进行比较来看一下是否相同,如果相同那么加进来这个字符之后变成了容易的串,那么这个字符应该舍弃
3. 具体的代码如下:
import java.util.Scanner;
public class Main{
static int n;
static int count;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int L = sc.nextInt();
dfs("", L);
}
private static void dfs(String s, int L) {
for(char c = 'A'; c < 'A' + L; c++){
if(isHard(s, c)){
String prefix = s + c;
System.out.println(prefix);
count++;
if(count == n){
System.exit(0);
}//不需要进行回溯,因为永远不会退回来去搜索它的平行状态
dfs(prefix, L);
}
}
}private static boolean isHard(String prefix, char c){
int count = 0;
for(int i = prefix.length() - 1; i >= 0; i -= 2){
String s1 = prefix.substring(i, i + count + 1);
String s2 = prefix.substring(i + count + 1) + c;
if(s1.equals(s2)) return false;
count++;
}
return true;
}
}
4. 判断是否为困难的串有是有传入的并不知道是什么样子的串,那么就需要对它所有的情况进行搜索
判断的代码如下:(调试的时候再截取完字符串之后使用输出语句查看输出的内容来判断代码判断是否正确)
import java.util.Scanner;
public class Main{
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
//System.out.println(s.substring(n - 1, n));
n = s.length();
isHard(s);
}private static void isHard(String s){
boolean flag = true;
for(int index = 1; index <= n / 2; index++){
for(int j = n; j - 2 * index >= 0; j -= index){
String prefix2 = s.substring(j - index, j);
String prefix1 = s.substring(j - 2 * index, j - index);
//System.out.println(prefix1 + " " + prefix2);
if(prefix1.equals(prefix2)){
System.out.println("不是一个困难的串");
flag = false;
break;
}
}
if(flag == false){
break;
}
}
if(flag){
System.out.println("是一个困难的串");
}
}
}