1018 单词接龙
2000年NOIP全国联赛普及组NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入描述 Input Description
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出描述 Output Description
只需输出以此字母开头的最长的“龙”的长度
样例输入 Sample Input
5
at
touch
cheat
choose
tact
a
样例输出 Sample Output
23
数据范围及提示 Data Size & Hint
(连成的“龙”为atoucheatactactouchoose)
#include <iostream>
#include <string>
#include <memory.h>
using namespace std;
string vocabulary[21];//存取输入的单词
int visited[21];//标记当前单词被访问的次数
int n;//输入的单词的数量
int Dlength=-1;//记录当前“龙”的最大长度
char beginC;//存取开头字母
//这个函数是用来连接两个字符串的,可以进行最大连接
//例如:"abecde" 和"ecdef"重叠的部分是"e"而不是"ecde"
//如果输入的两个字符串不能连接,则返回"",能连接则返回连接后的字符串
string connectStr(string &a, string &b)
{
int i, j;
j = 1;
int aL = a.length();
int bL = b.length();
string tempa, tempb;
for (i=aL-1;i>=0;--i)//从a的末尾开始
{
tempa = a.substr(i, j);
tempb = b.substr(0, j);
if (tempa==tempb&&tempa!=a&&tempb!=b)break;//有重叠的部分,且不是互相包含
j++;
}
if (i==-1) return "";
else return (a + b.substr(j, bL - j));
}
void dfs(string src)
{
for (int i=1;i<=n;i++)//遍历所有单词
{
string together = connectStr(src, vocabulary[i]);//连接
if (together!=""&&visited[i]!=2)
{
int L = together.length();
if (L>Dlength)
Dlength = together.length();
visited[i]++;
dfs(together);
visited[i]--;
}
}
}
int main()
{
cin >> n;
for (int i=1;i<=n;i++)
cin >> vocabulary[i];
cin >> beginC;
memset(visited, 0, sizeof(visited));
//以上是输入和初始化部分
for (int i=1;i<=n;i++)//这个循环是用来遍历给定字母开头的单词
{
if (vocabulary[i][0]==beginC)
{
visited[i] = 1;//开头的单词使用了一次
if (vocabulary[i].length()>Dlength)
Dlength = vocabulary[i].length();//至少是当前开头单词的长度
dfs(vocabulary[i]);
visited[i] = 0;
}
}
cout << Dlength;
cin >> Dlength;
}