题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeast和astonishastonis**h,如果接成一条龙则变为beastonishbeastonis**h,另外相邻的两部分不能存在包含关系,例如ata**t 和 atideatide 间不能相连。
输入格式
输入的第一行为一个单独的整数nn (n \le 20n≤20)表示单词数,以下nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入 #1复制
5
at
touch
cheat
choose
tact
a
输出 #1复制
23
说明/提示
(连成的“龙”为atoucheatactactouchoose)
NOIp2000提高组第三题
注意:
- 一个单词最多用两次
- 单词可以不全用完
- 不可以包含:包含就是没有用
- 按照贪心原则,重叠部分应该越少越好
这道题就是搜索,从指定字母开头的字符串开始,用指定字符串的后缀匹配可能连接的前缀,
层层套娃
import java.util.Arrays;
import java.util.Scanner;
public class P1019_单词接龙 {
static String[] sts=new String[21];
static int[] arr=new int[21];
static int n;
static String max="";
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
for (int i = 1; i <=n; i++) {
sts[i]=sc.next();
}
String st=sc.next();
for (int i = 1; i <=n; i++) {
//这个字符串的头是指定的字母,以这个字符串为首开始匹配
if(sts[i].charAt(0)==st.charAt(0)){
arr[i]=1;
DFS(sts[i],arr);
Arrays.fill(arr,0);
}
}
System.out.println(max.length());
}
private static void DFS(String st,int[]ars) {
for (int i = 1; i <=n; i++) {
//在得出结果之前continue
if(ars[i]>=2) continue;
//拼接字符串,如果不符合拼接条件返回空串
String st1=chenk(st,sts[i]);
//如果拼接后的字符串和原串相等continue
if(st.equals(st1)) continue;
//如果拼接后的串更大那么记录下来
if(st1.length()>max.length()) max=st1;
//默认串也有可能是最大串
if(st.length()>max.length()) max=st;
if(st1!=""){
ars[i]++;
DFS(st1,ars);
ars[i]--;
}
}
}
//拼串,可以就拼接,不可拼接返回空串
private static String chenk(String st, String st1) {
int a=st.length()-1,b=1;
while (b<st1.length()&&a>=0){
//后缀去匹配前缀
if(st.substring(a,st.length()).equals(st1.substring(0,b))){
return st+st1.substring(b,st1.length());
}
a--;
b++;
}
return "";
}
}