[NOIP2000 提高组] 单词接龙
题目背景
注意:本题为上古 NOIP 原题,不保证存在靠谱的做法能通过该数据范围下的所有数据。
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast
和 astonish
,如果接成一条龙则变为 beastonish
,另外相邻的两部分不能存在包含关系,例如 at
和 atide
间不能相连。
输入格式
输入的第一行为一个单独的整数 n n n 表示单词数,以下 n n n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出格式
只需输出以此字母开头的最长的“龙”的长度。
样例 #1
样例输入 #1
5
at
touch
cheat
choose
tact
a
样例输出 #1
23
提示
样例解释:连成的“龙”为 atoucheatactactouchoose
。
n ≤ 20 n \le 20 n≤20。
思路:
1.输入数据
2.从n个单词中寻找以字符c开头的单词
3.dfs
. 如果拼接后的单词长度大于 ans 更新ans
. 枚举所有单词
. 如果能够拼接 返回拼接后的字符串
. vis 标志位加一
. dfs
. 回退vis 标志位
4.输出 ans
Code:(c语言)
c语言没有string类型 写起来比较麻烦 特别是单个字符输入会有问题 建议采用c++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int n, ans =0, vis[25] = {0};
char str[25][25], c;
bool strcon(char *str1, char *str2){ //判断是否可以连接 如果可以,将连接后的单词返回给str1并返回true 否则返回false
int len1 = strlen(str1), len2 = strlen(str2);
char sub1[1024], sub2[1024];
memset(sub1, '\0', sizeof(sub1));
memset(sub2, '\0', sizeof(sub2)); //初始化子串
int i;
for(i = 1; i < len1 && i < len2; i++){ //将i个字符的子串进行比较
strcpy(sub1, &str1[len1-i]); //截取子串1 从第len1-1开始 复制 到末尾
strncpy(sub2, str2, i); //截取子串2 从第0个开始 复制 i个
if(strcmp(sub1, sub2) == 0){ //相等
strcpy(sub2, &str2[i]);
strcat(str1, sub2); //接龙
return true;
}
}
return false;
}
void dfs(char *s){ //搜索
char temp[1024]; //临时变量 用来存储接龙单词
memset(temp, '\0', sizeof(temp)); //初始化为空串
strcpy(temp, s); //复制s给temp
if(strlen(temp) > ans){ //单词长度大于已经存储的长度就更新长度
ans = strlen(temp);
}
int i;
for(i = 0; i < n; i++){ //枚举所有单词
if(vis[i] == 2) continue; //已经有两次不再搜索
if(strcon(temp, str[i])){ //判断是否能连接
vis[i]++; //标志位加1
dfs(temp); //新的单词继续搜索
vis[i]--; //标志位回退
strcpy(temp, s); //单词回退
}
}
}
int main(){
memset(str, '\0', sizeof(str));
scanf("%d", &n);
int i;
for(i = 0; i < n; i++){
scanf("%s\n", str[i]);
}
scanf("%c", &c);
for(i = 0; i < n; i++){
if(str[i][0] == c){
vis[i]++;
dfs(str[i]);
vis[i]--;
}
}
printf("%d", ans);
return 0;
}
Code:(c++)
#include <bits/stdc++.h>
using namespace std;
int n, ans =0, vis[25] = {0};
char c;
string str[25];
string strcon(string s1, string s2){
int len1 = s1.length(), len2 = s2.length();
for(int i = 1; i < len1 && i < len2; i++){
if(s1.substr(len1-i, i) == s2.substr(0, i)){ //子串函数 从第一个参数位置截取 第二个参数个字符
return s1.substr(0, len1-i) + s2;
}
}
return "0";
}
void dfs(string s){
if(s.length() > ans){
ans = s.length();
}
for(int i = 0; i < n; i++){
if(vis[i] < 2 && strcon(s, str[i]) != "0"){
vis[i]++;
dfs(strcon(s, str[i]));
vis[i]--;
}
}
}
int main(){
cin >> n;
for(int i; i < n; i++){
cin >> str[i];
}
cin >> c;
for(int i = 0; i < n; i++){
if(str[i][0] == c){
vis[i]++;
dfs(str[i]);
vis[i]--;
}
}
cout << ans;
return 0;
}