洛谷P1019

来一道简单的递归

 

题目如下:

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1
5
at
touch
cheat
choose
tact
a
输出 #1
23

说明/提示

样例解释:连成的“龙”为 atoucheatactactouchoose

n \le 20n20

 

分析一下: 

1. 单词不能被包含。

2. 单词最多能使用两次。

3. n最大为20,可以考虑递归深搜

package pro.luogu;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class P1019 {
    private static int ans, n;
    private static int[] visited;
    private static String[] strs;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());//单词数量
        strs = new String[n]; //单词数组
        visited = new int[n];//使用次数数组

        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            strs[i] = st.nextToken();
        }
        st = new StringTokenizer(br.readLine());
        String start = st.nextToken();// 开始拼接的单个字符

        ans = 0;//最开始的长度为0
        dfs(start);
        System.out.println(ans);

//        System.out.println(checkDuplicate("touch","uchu"));
    }

    //简单递归
    private static void dfs(String end) {
        for (int i = 0; i < n; i++) {
            if(visited[i] < 2) { // 使用次数不到两次,就可以使用
                //判断当前第i个单词是否能够使用,不能使用返回-1,可以使用返回第i个单词的重叠部分的索引
                int duplicate = checkDuplicate(end, strs[i]);
                if(duplicate != -1) {
                    visited[i]++;//可以使用,使用次数加一
                    if((end+strs[i].substring(duplicate+1)).length() > ans) {//拼接的新单词长度进行对比
                        //更新最大拼接的长度
                        ans = (end+strs[i].substring(duplicate+1)).length();
                    }
                    dfs(end+strs[i].substring(duplicate+1));//可以成功拼接继续递归
                    visited[i]--;//回溯的时候需要将使用次数减一。以防下一波循环又可以用
                }
            }
        }
    }

    // 判断单词重复的部分
    private static int checkDuplicate(String start, String str) {
        // 获取较短的字符串长度
        int len = start.length() > str.length() ? str.length() : start.length();

        for (int i = 0; i < len; i++) {
            //如果str的前面截取和start最后的截取一致就进入
            if(str.substring(0, i+1).equals(start.substring(start.length()-1-i))) {
                //如果是单个字符,不用判断是否包含,其他字符需要判断是否全部被使用。
                if(i != len-1 || start.length() == 1) {
                    return i; //返回索引
                }
            }
        }

        return -1;//返回失败索引
    }
}

 

posted @ 2020-11-11 16:24  姓蜀名黍  阅读(183)  评论(0)    收藏  举报