ALGO-18 单词接龙 —— DFS与字符串处理(java)

前言:

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


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值