java:单词接龙(dfs)(重点看看:包括相同单词不包含,还有找到第一个相同的开头单词相同的字母,连接字符串重复部分删除)

java:单词接龙

题目

问题描述

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

输入格式

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

输出格式

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

样例输入
  5
  at
  touch
  cheat
  choose
  tact
  a
样例输出
23
样例说明
  连成的“龙”为atoucheatactactouchoose
import java.util.Scanner;

public class 单词接龙 {
	//字符串
	private static String[] a;
	private static int n,max=0;//单词个数
	private static int visit[];
	private static String tmp,s,s1;
	private static char st;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n = sc.nextInt();
		a = new String[n];
		for(int i=0;i<n;i++){
			a[i]=sc.next();
		}
		s=sc.next();
		st=s.charAt(0);
		visit=new int[n];
		for(int i=0;i<n;i++){
			if(findS1(a[i])){
				dfs(s1);//从第一个单词开始
			}
		}
		System.out.println(max);
	}
	//是否找到第一个单词
	private static boolean findS1(String a) {
		// TODO Auto-generated method stub
		char ss[]=a.toCharArray();
		if(ss[0]==st){
			s1=a;//开始的单词就为a
			return true;
		}else{
			return false;
		}
	}
	//s的状态会改变,长度会改变
	public static void dfs(String ss){
		//先进行匹配,从开头的一个字母出发,之后一个个进行匹配,如果大于这个数就标记位正确的
		String temp="";
		temp=ss;
		if(max<=ss.length()){
			max=ss.length();
		}
		//从0开始查找
		for(int i=0;i<a.length;i++){
			//ss和当前字符串开始连接和判断时不是相同的字符串,相同的不可以连接,还有没有访问过
			if(visit[i]<2&&checkString(ss,a[i])&&contact(ss,a[i])){
				visit[i]++;
				ss=tmp;//两个单词连接之后的,
				dfs(ss);//在把这个连接了的再进行遍历
				ss=temp;//如果不是,ss还是等于之前的temp
				visit[i]--;//并回溯
			}
		}

	}
	private static boolean checkString(String a, String b) {
		// TODO Auto-generated method stub
		String a1;
		String b1;
		//相同的单词不包含
		if(a.length()<=b.length()){
			a1=a;
			b1=b;
		}else{
			a1=b;
			b1=a;
		}
		char a11[]=a1.toCharArray();
		char b11[]=b1.toCharArray();
		if(a1.equals(b1)){
			return true;
		}
		for(int i=0;i<a11.length;i++){
			if(a11[i]!=b11[i]){
				return true;
			}
		}
		return false;
	}
	public static boolean contact(String a,String b){
		char s11[]=a.toCharArray();
		char s22[]=b.toCharArray();
		for(int j=0;j<b.length()&&j<a.length();j++){
			//s11的最后一个字母等于s22的字母,这个如果是一个连续的字母,例如ch chest,最后一个字母就等于第二个字母
			if(s11[s11.length-1]==s22[j]){
				//s11从后往前检查,s22从前往后检查
				for(int k1=s11.length-1,k2=j;k1>=0&&k2>=0;k1--,k2--){
					if(s11[k1]!=s22[k2]){
						return false;
					}
					//当k2到了开头的位置
					if(k2==0){
						//从j+1开始往后面取
						b=b.substring(j+1);
						tmp=a+b;//进行连接了
						return true;
					}
				}
			}
		}
		return false;
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向上Claire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值