【题目描述】
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们己知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙" 中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
【输入】
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输 入的最后一行为一个单个字符,表来“龙”开头的字母。你可以假定以此字母开头的“龙" 一定存在。
【输出】
只需输出以此字母开头的最长的“龙”的长度
【输入样例】
5
at
touch
cheat
choose
tact
a
【输出样例】
23
【提示】
样例连成的“龙”为atoucheatactactouchoose
废话不多说,AC代码启动!
#include<bits/stdc++.h>
using namespace std;
#define N 25
int n, totLen, mxLen;//totLen:龙当前长度 mxLen:龙最大长度
string s[N];//s[i]:单词列表第i个单词
int vis[N];//vis[i]:单词s[i]用了几次
void dfs(string ls)//ls:当前龙中最后字符串
{
mxLen = max(totLen, mxLen);//取可能的最大的长度
for(int i = 1; i <= n; ++i)
{
if(vis[i] < 2)//只要用了不足2次
{
int len;//ls与s[i]重合部分的长度
for(len = 1; len < ls.length() && len < s[i].length(); ++len)//由于重合部分不能包含单词,所以重合部分长度要小于两单词的长度
{//将ls末尾len个字符截取出来,看和s[i]前len个字符是否相同
if(ls.substr(ls.length()-len, len) == s[i].substr(0, len))//只要找到一个可以接上的情况,就不再找了,再找到的不会是最长的龙
break;
}
if(len < ls.length() && len < s[i].length())//从上面循环中间跳出,表明s[i]可以接在ls后面。如果不满足该条件,说明循环运行到了最后,没有重合部分。
{
vis[i]++;//s[i]多用了1次
totLen += s[i].length() - len;//总长度增加s[i].length() - len
dfs(s[i]);
totLen -= s[i].length() - len;//恢复状态
vis[i]--;
}
}
}
}
int main()
{
char stch;//起始字符
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> s[i];
cin >> stch;
for(int i = 1; i <= n; ++i)
{
if(s[i][0] == stch)//如果起始字符和s[i]首字符相同
{//以s[i]起始
vis[i]++;
totLen = s[i].length();//当前总长度为s[i]的长度
dfs(s[i]);
vis[i]--;//恢复状态
}
}
cout<<mxLen;
return 0;
}
给个关注算是支持我,球球了QAQ
文章详细展示了如何使用C++编写程序解决单词接龙问题,通过深度优先搜索和限制单词重复使用次数,计算以特定字母开头的最长单词链。
390

被折叠的 条评论
为什么被折叠?



