计算最长英语单词链
大家经常玩成语接龙游戏,我们试一试英语的接龙吧:一个文本文件中有N 个不同的英语单词, 我们能否写一个程序,快速找出最长的能首尾相连的英语单词链,每个单词最多只能用一次。最长的定义是:最多单词数量,和单词中字母的数量无关。
统一输入文件名称:input1.txt, input2.txt
统一输出文件名称:output1.txt,output2.txt
程序需要考虑下列异常状况:
例如,文件不存在,你的程序会崩溃么,还是能优雅地退出并给用户提示信息?
如果文件没有任何单词、只有一个单词、没有可以首尾相连的单词,程序应该如何输出?
如果输入文件有一万个单词,你的程序能多快输出结果?
package dancilian;
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);
}
}