题目链接
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish ,如果接成一条龙则变为 beastonish ,另外相邻的两部分不能存在包含关系,例如 at 和 atide 间不能相连。
输入输出格式
输入格式:
输入的第一行为一个单独的整数 n ( n≤20 )表示单词数,以下 n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式:
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入样例#1:
5
at
touch
cheat
choose
tact
a
输出样例#1:
23
说明
(连成的“龙”为atoucheatactactouchoose)
NOIp2000提高组第三题
//代码有注释,下方提供纯代码(无注释)
#include<bits/stdc++.h>
using namespace std;
string s[25];
int n,ans,add[25][25],visited[25];//add[][]数组记录的是两个可以连接的字符串合并之后重合部分的长度
//预处理的目的是统计哪些字符可以相连,若可以相连的话,连接之后重合的长度保存在add[][]数组中
void deal(int indx1,int indx2){//用s[indx1]去匹配s[indx2]!!
int len1,len2,len,k,flag;
len1 = s[indx1].size();
len2 = s[indx2].size();
len = min(len1,len2);
for(int i = 1;i <= len;i++){//枚举所有重合的可能长度,从i开始,直到len
flag = 0;//初始化flag变量为0
k = i;
for(int j = 0;j < i;j++)
//若两者不相等,就说明可以继续枚举寻找相等的,把flag变量置为1
if(s[indx1][len1 - i + j] != s[indx2][j]){
flag = 1;
break;
}
//asss ssb 连接起来是assssb 长度为6,而不是!!assb!!
if(!flag)//如果已经枚举到一个符合条件的最大重合长度(即最小的k),则退出循环,不用继续向下寻找
break;
}
//flag == 1,记录最大重合长度,用len2 - k,(不是len1 - k) && 枚举的最大长度小于len,说明不存在包含关系
if(!flag && k < len)
add[indx1][indx2] = len2 - k;
return;
}
void dfs(int index,int mx){
ans = max(ans,mx);
for(int i = 0;i < n;i++){
if(visited[i] == 2 || !add[index][i])
continue;
visited[i]++;
dfs(i,mx + add[index][i]);
visited[i]--;
}
return;
}
int main(){
scanf("%d",&n);
for(int i = 0;i <= n;i++)
cin >> s[i];
for(int i = 0;i < n;i++)
for(int j = 0;j < n;j++)
deal(i,j);//预处理每一个单词
for(int i = 0;i < n;i++)//每一个首字母相同的都要试一试
if(s[n][0] == s[i][0]){
visited[i]++;
dfs(i,s[i].size());
visited[i]--;
}
printf("%d\n",ans);
return 0;
}
//无注释代码
#include<bits/stdc++.h>
using namespace std;
string s[25];
int n,ans,add[25][25],visited[25];
void deal(int indx1,int indx2){
int len1,len2,len,k,flag;
len1 = s[indx1].size();
len2 = s[indx2].size();
len = min(len1,len2);
for(int i = 1;i <= len;i++){
flag = 0;
k = i;
for(int j = 0;j < i;j++)
if(s[indx1][len1 - i + j] != s[indx2][j]){
flag = 1;
break;
}
if(!flag)
break;
}
if(!flag && k < len)
add[indx1][indx2] = len2 - k;
return;
}
void dfs(int index,int mx){
ans = max(ans,mx);
for(int i = 0;i < n;i++){
if(visited[i] == 2 || !add[index][i])
continue;
visited[i]++;
dfs(i,mx + add[index][i]);
visited[i]--;
}
return;
}
int main(){
scanf("%d",&n);
for(int i = 0;i <= n;i++)
cin >> s[i];
for(int i = 0;i < n;i++)
for(int j = 0;j < n;j++)
deal(i,j);
for(int i = 0;i < n;i++)
if(s[n][0] == s[i][0]){
visited[i]++;
dfs(i,s[i].size());
visited[i]--;
}
printf("%d\n",ans);
return 0;
}