洛谷P1019 Java解法

题目出处点这里
洛谷P1019 Java解法_第1张图片
思路:dfs暴力搜出所有情况记录长度最大值即可
找到每一个可以作为头的字符串不断与其他字符串进行拼接,然后把拼接后的字符串接着与其它字符串不断拼接,取所有情况的长度最大值。值得注意的是有可能你找到·了一个可以当头的字符串,但是它不能和任何字符串进行拼接,可是它的长度就是最大的,因此不管头字符串能不能拼接成功,我们都要判断头字符串的长度是不是最大的。

代码一看就懂(超详细的注释):

package search;

import java.util.Arrays;
import java.util.Scanner;

public class P1019 {

	static int n, max,arr[];// max记录拼接后的最长字符串的长度, arr[]记录每个字符串的使用次数
	static String sArr[], head;// sArr存储n个字符串,head代表头字母

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		// 接收数据
		n = sc.nextInt();
		arr = new int[n];
		sArr = new String[n];
		for (int i = 0; i < n; i++) {
			sArr[i] = sc.next();
		}
		head = sc.next();
		
		for (int i = 0; i < n; i++) {// 遍历每一个字符串看看哪些可以作为开头
			if (sArr[i].charAt(0) == head.charAt(0)) {
				arr[i] = 1;// 如果可以作为开头,就用这个并把其置为已经使用了一次
				dfs(sArr[i]);//开始用这个开头搜
				Arrays.fill(arr, 0);//每次以一个开头搜完记得把记录每个字符串使用次数的数组arr全置为0,以供下一次使用
			}
		}
		System.out.println(max);
	}

	/**
	 * 
	 * @param headString 作为开头的字符串
	 */
	public static void dfs(String headString) {
		for (int i = 0; i < n; i++) {// 遍历每一个字符串,看看哪个可以拼接
			if (arr[i] == 2) {// 如果该字符串已经用过两次,那么continue
				continue;
			}
			if (headString.length()>max) {//有可能该头字符串匹配不到任何字符串,但它本身的长度就是最大的
				max = headString.length();
			}
			
			String s = stitching(headString, sArr[i]);// s代表拼接完成后的字符串
			if (s == "") {//如果字符串是空的,continue即可
				continue;
			}
			//如果拼接后的字符串和原来的字符串长度有相同的,那就说明其中有字符串被包含,直接continue即可
			if (s.length() == headString.length() || s.length() == sArr[i].length()) {
				continue;
			}
			
			if (s.length()>max) {//如果拼接后的字符串长度大于max
				max = s.length();
			}
			arr[i]++;
			dfs(s);//进行下一次拼接,以已经拼接好的字符串为头
			arr[i]--;//回溯:拼好后要把相应字符串所用次数减一,以便其余拼接方法使用

		}
	}

	// 写一个方法拼接字符串
	/**
	 * 要使字符串长度尽量大,那么只要headString的末尾和tailString的开头有相同的字符,就进行拼接
	 * 
	 * @param headString 待拼接的放在前面的字符串
	 * @param tailString 待拼接的放在后面的字符串
	 * @return 能拼接成功就返回拼接后的字符串,没拼接成功就返回空串
	 */
	public static String stitching(String headString, String tailString) {
		// 前者后缀匹配后者前缀
		int a = headString.length() - 1;
		int b = 1;
		while (a >= 0 && b <= tailString.length() - 1) {// 只要不超出各自的长度就一直找,直到找到可以匹配的字符为止

			if (headString.substring(a, headString.length()).equals(tailString.substring(0, b))) {
				// 要使字符串长度尽量,因此一旦匹配到就直接return
				return headString + tailString.substring(b, tailString.length());
			}
			a--;// a前移
			b++;// b后移
		}
		return "";/// 如果这两个字符串无法拼接,就返回空串
	}
}

你可能感兴趣的:(洛谷)