前言:
药丸啊药丸啊真的药丸啊,几天时间没做题,昨天做了一道单词接龙题,做了一整个晚上啊,大几个小时。本来想昨天十一点多的时候,也就是好不容易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); } }