题目描述
如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”。例如, BB、ABCDABCD都是容易的串,而D、DC、ABDAD、CBABCBA都是困难的串。
输入正整数n和L,输出由前L个字符组成的、字典序第n个困难的串。例如,当L=3时,前7个困难的串 分别为A、AB、ABA、ABAC、ABACA、ABACAB、ABACABA。输入保证答案不超过80个字符。
样例输入:
7 3
30 3
样例输出:
ABACABA
ABACABCACBABCABACABCACBACABA
题目理解
困难的串:串中不含有相邻的相同子串 如ABAC
容易的串:含有相邻且相同的字串 如ABAB
输入L代表要找的串长
输入n代表所用到的前n个字符ABC…
要求 找到长度为L 前n个字典序最小的字符串(大写字母组成)
解体思路
往一个字符串中不断添加字母,要求字典序最小,所以能想到每次添加A,但是有要求无重复字串,所以要添加一个判断,若加入A之后,所构成的串变成了容易的串,就要舍弃加入A,转而加入B,同理一直往后判断,一直找到能构成困难的串的那个字母。
这种寻找的顺序很容以就能想到使用dfs来做。
两个难点
- 判断一个串加入某个字母后是否变成了容易的串
- dfs这个函数应该怎么写
代码
public class 困难的串 {
public static void main(String[] args) {
dfs("",7,3);
}
static int count=0;
public static void dfs(String str,int n,int l) {
for(char i='A';i<'A'+l;i++) {
if(isHard(str,i)) {
str = str+i;
System.out.print(i);
count++;
if(count==n) {
System.exit(0);
}
dfs(str,n,l);
}
}
}
public static boolean isHard(String prefix,char i) {
int count = 0;
for(int j=prefix.length()-1;j>=0;j-=2) {
String s1 = prefix.substring(j,j+count+1);
String s2 = prefix.substring(j+count+1)+i;
if(s1.equals(s2)) {
return false;
}
count++;
}
return true;
}
}
代码剖析
public static boolean isHard(String prefix,char i) {
int count = 0;
for(int j=prefix.length()-1;j>=0;j-=2) {
String s1 = prefix.substring(j,j+count+1);
String s2 = prefix.substring(j+count+1)+i;
if(s1.equals(s2)) {
return false;
}
count++;
}
return true;
}
这个函数用于判断加入字符后是否仍然是困难得到串
指针j首先指向串尾 此后每次向后退两个位置 为什么是退两个而不是退一个哪
假如我们称加入的字符A 为 加入字符
我们想要比较的是 每次对加入字符添加一个字符 然后和他相邻同等长度的他前面那个子串进行比较。
由于每次给前面的加入字符分配一个字符 自己也要增加一个长度 所以每次往后退两个位置。
int count=0;
for(int j=prefix.length()-1;j>=0;j-=2) {
String s1 = prefix.substring(j,j+count+1);
String s2 = prefix.substring(j+count+1)+i;
if(s1.equals(s2)) {
return false;
}
下面仔细看substring函数里面的内容 s1从j指针开始 到j+count+1结束(不包括j+count+1)。这个count在控制每次所比较的子串长度,每次长度加1
s2从j+count+1开始直到最后。这里也能体现为什么j每次减2。
public static void dfs(String str,int n,int l) {
for(char i='A';i<'A'+l;i++) {
if(isHard(str,i)) {
str = str+i;
System.out.print(i);
count++;
if(count==n) {
System.exit(0);
}
dfs(str,n,l);
}
else return;
}
}
这段代码充分体现了dfs的思想.需要注意的是 对字符的操作可以直接加上一个整型数字来运算。