P1019 [NOIP 2000 提高组] 单词接龙
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast
和 astonish
,如果接成一条龙则变为 beastonish
,另外相邻的两部分不能存在包含关系,例如 at
和 atide
间不能相连。
输入格式
输入的第一行为一个单独的整数 n 表示单词数,以下 n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出格式
只需输出以此字母开头的最长的“龙”的长度。
输入输出样例
输入
5 at touch cheat choose tact a
输出
23
说明/提示
样例解释:连成的“龙”为 atoucheatactactouchoose
。
n≤20。
解题思路
这道题要求两个字符串要有连接部分,但是又不能互相包含,并且每个字符串使用不能超过两次,最后将所有字符串连起来后计算最后字符串的总长度然后输出
题目要求首个字母必须是c,那么我们输入所有字符串后先查询有没有首字母和c相同的,那么就以这个为龙头进行dfs
在dfs函数中,我们可以先存入字符串的长度,随后在循环中查找符合要求的字符串,在查询每一个字符串后记得标记,如果访问次数大于2那就跳过。
查询字符串时,我们可以使用substr函数进行剪切,如果符合要求那就返回剪切后的字符串,如果找不到符合要求的就返回“0”,在dfs函数中也要记得判断一下更新后的字符串是否为“0”,如果不为0才可以继续进行dfs
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,mark[30]={0},sum=0;
string s[30];
string pd(string len1,string len2)
{int a=len1.size(),b=len2.size();for(int i=1;i<a&&i<b;i++){if(len1.substr(a-i,i)==len2.substr(0,i)){return len1.substr(0,a-i)+len2;}}return "0";
}
void dfs(string drag)
{if(sum<drag.size()){sum=drag.size();} for(int i=0;i<n;i++){if(mark[i]<2){string stl=pd(drag,s[i]);if(stl!="0"){mark[i]++;dfs(stl);mark[i]--;}}}
}
int main()
{char c;cin>>n;for(int i=0;i<n;i++){cin>>s[i];}cin>>c;for(int i=0;i<n;i++){if(s[i][0]==c){mark[i]++;dfs(s[i]);mark[i]--;}}cout<<sum;return 0;
}