DFS-单词接龙

题目描述

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

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

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

输入
5
at
touch
cheat
choose
tact
a
输出
23
说明/提示(连成的“龙”为atoucheatactactouchoose)

import java.util.Scanner;
public class 单词接龙2 {
    static int n,ans;
    static int [][]dic=new int[21][21];
    static int[]vis=new int[21];
    static String [] word=new String[21];
    static char s;
    static void f(String a,String b,int x,int y)
    {
        int a1=a.length()-1,b1=b.length()-1;
        for(int i=0;i<=b1;i++)  //从第一个开始枚举
        {
            if(a.charAt(0)==b.charAt(i))  //如果a的首字母和b的字母相同 ,则判断它们能不能接在一起
            {
                int pos=0,tot=0;  //pos是当前a的第几个字母,tot是a和b的重合部分长度
                for(int j=i;j<=b1;j++)
                {
                    if(a.charAt(pos)==b.charAt(j))
                    {
                        tot++;
                        pos++;
                        if(j==b1&&tot!=Math.min(a1,b1)+1) //如果枚举到了最后,并且a和b没有包含关系,说明可以这么接
                            dic[x][y]=tot;  //记录最小重叠部分的长度
                        //之所以不break,是因为后面可能还会枚举到更小的接法
                        //比如 chsese 和 sesettt 显然 chsesesettt 要比chsesettt更优
                    }
                    else break;
                }
            }
        }
    }
    static void dfs(int pos,int sum)
    {
        ans=Math.max(ans,sum);  //实时更新ans
        for(int i=1;i<=n;i++)
        {
            if(dic[i][pos]>0&&vis[i]>0)
            {
                vis[i]--;
                int suml=sum+word[i].length()-dic[i][pos]; //接上新单词"龙"的长度为=旧的长度+新单词长度-重复部分长度
                dfs(i,suml);  //接上新单词继续搜索
                vis[i]++;
            }
        }
    }
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        n=scanner.nextInt();
        for (int i = 1; i <=n ; i++) {
            word[i]=scanner.next();
            vis[i]=2;
        }
        s=scanner.next().charAt(0);
        for (int i = 1; i <=n ; i++) {//i,j 用dic记录第i个单词和第j个单词的重叠情况,例如dic[4][3]=2表示第四个接第三个重叠两个
            for (int j = 1; j <=n ; j++) {
                f(word[i],word[j],i,j);
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(word[i].charAt(0)==s)  //找到开始部分
            {
                vis[i]--;
                dfs(i,word[i].length()); //深搜
                vis[i]++;
            }
        }
        System.out.println(ans);

    }
}

你可能感兴趣的:(#,DFS)