前言:
药丸啊药丸啊真的药丸啊,几天时间没做题,昨天做了一道单词接龙题,做了一整个晚上啊,大几个小时。本来想昨天十一点多的时候,也就是好不容易AC了之后就写题解的,可是AC了之后反而身心俱疲,感觉自己蒟蒻,心态收到了冲击。
今天上完课写完作业后,还是心有余悸... 再好好地回顾一下,写一篇题解吧。
分析:
这道题的tag是搜索,但是其实还有字符串处理混杂在里面。
首先,理解题意就是一个坎,如果不是写到实在思维混乱了,重新研究了一些样例数据,我可能就一直在错误的理解下挣扎了。仔细去看样例给出的五个单词at touch cheat choose tact, 最终以 a开头的最长的龙是atoucheatactactouchoose。
要注意什么呢,题意要求,在两个单词相连时,其重合部分合为一个部分,也就是说,只有把单词的最小重合部分合并,才能保证最大,并且,要连就要整个单词连上去,不能截取。那么所受到的限制就仅仅是末尾最后一次接上的串了。一定要理清这个思路,否则会绕晕。
另外一个注意点时,每个单词最多用两次,那就用int数组去计数,不要用boolean了。
最后要特别注意的是,题目指出,相邻的部分不能存在包含关系,但是!如果是自身和自身连接,是不属于在包含关系里的,也就是说,允许自身和自身进行连接!
还有其他的一些边边角角的就都写在注释里吧。
实现:
import java.util.Scanner;
public class Main {
static int n = 0, result = 0;
static String[] word; // 记录字符串
static char first; // 记录开头的字母
static int visit[]; // 记录单词出现的次数
static String link; // 记录连接串
// dfs搜索
static void dfs(String str) {
String temp = str;
if (result <= str.length()) {
result = str.length();
}
for (int i = 0; i < word.length; i++) {
if (visit[i] < 2 && connect(str, word[i])
&& check(str, word[i]) == false) {
visit[i]++;
dfs(link);
str = temp; // 一定要回溯!不要改变str!
visit[i]--;
}
}
}
// 检查是否为最小重合部分
static boolean connect(String a, String b) {
char a1[] = a.toCharArray();
char b1[] = b.toCharArray();
for (int i = 0; i < Math.min(a.length(), b.length()); i++) {
// 如果a1末尾的和a2开头的相等
if (a1[a1.length - 1] == b1[i]) {
// 两个串分别往前推着检查
for (int j = a1.length - 1, k = i; j >= 0 && k >= 0; j--, k--) {
if (a1[j] != b1[k]) {
return false;
}
// 如果检查直到b1的第一位,都相等,则找到了重合部分
if (k == 0) {
b = b.substring(i + 1);// 取出这个重合部分,留下后面的字符串
link = a + b;// 形成连接串
return true;
}
}
}
}
return false;
}
// 检查是否有包含关系
public static boolean check(String a, String b) {
// 相同不算在包含的情况下
if (a.equals(b)) {
return false;
}
// 没有包含关系:
for (int i = 0; i < Math.min(a.length(), b.length()); i++) {
if (a.charAt(i) != b.charAt(i)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
word = new String[n];
for (int i = 0; i < n; i++) {
word[i] = sc.next();
}
first = sc.next().charAt(0);
visit = new int[n];
sc.close();
for (int i = 0; i < word.length; i++) {
if (word[i].charAt(0) == first) {
dfs(word[i]);
}
}
System.out.println(result);
}
}