P1019 单词接龙

P1019 单词接龙

题目描述

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeast和astonishastonish,如果接成一条龙则变为beastonishbeastonish,另外相邻的两部分不能存在包含关系,例如atat 和 atideatide 间不能相连。

输入格式

输入的第一行为一个单独的整数nn (n \le 20n≤20)表示单词数,以下nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式

只需输出以此字母开头的最长的“龙”的长度

输入样例

5
at
touch
cheat
choose
tact
a

输出样例

23

题解

import java.util.Scanner;

public class Main {

	public static int n;
	public static String inStr[] = new String[21];//存储字符串
	public static int length = 0;//记录结果字符串长度
	public static int flag[] = new int[21];//存储字符串用过的次数
	
	//返回重叠部分的长度
	public static int Splicing(String left, String right) {
		for(int i=left.length()-1,k=1;i>=1;i--,k++) {
			if (right.length()-k > 0) {
				if(left.substring(i, left.length()).contains(right.substring(0, k))) {
					return k;
				}
			}
		}
		return 0;
	}
	
	//回溯主体
	public static void Search(String now, int nowlength) {
		//判断长度
		if(nowlength > length) length = nowlength;
		//横向搜索
		for(int i=0;i<n;i++) {
			//判断用过的字符串次数
			if(flag[i]>=2) continue;
			int k = Splicing(now, inStr[i]);
			//纵向搜索
			if(k > 0) {
				flag[i]++;
				Search(inStr[i],nowlength+inStr[i].length()-k);
				flag[i]--;
			}
		}
	}
	
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		for(int i=0;i<=n;i++) {
			inStr[i] = scanner.next();
		}
		for(int i=0;i<n;i++) {
			if(inStr[i].startsWith(inStr[n])) {
				flag[i]++;//第一个单词也要记得加使用次数
				Search(inStr[i], inStr[i].length());
				flag[i]--;
			}
		}
		System.out.println(length);
		scanner.close();
	}

}

总结

大致了解了深搜的规律之后,这道题也比较容易理解和解决了。我们来理解一下题意,这道题的目的得到是一个整数,即“龙”的长度。然后可以看到它给出的限制每个单词只能出现两次,取最长的“龙”。所以在我们的回溯主体要有两个判断,第一个是判断长度取最长,第二个是判断单词是否出现两次。解决这两个判断之后,不断回溯即可得到正确结果。在这里面有一个单词拼接的操作,我们单独写出一个函数来执行这个操作,因为题目所求只是长度,所以这个拼接函数返回两个单词的最小重叠的长度即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值