题目来源:
https://www.luogu.org/problemnew/show/P1019
题目描述:
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beastbeast 和 astonishastonish ,如果接成一条龙则变为 beastonishbeastonish ,另外相邻的两部分不能存在包含关系,例如 atat 和 atideatide 间不能相连。
输入输出格式
输入格式:
输入的第一行为一个单独的整数 nn ( n \le 20n≤20 )表示单词数,以下 nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式:
只需输出以此字母开头的最长的“龙”的长度
输入输出样例
输入样例#1: 复制
5 at touch cheat choose tact a
输出样例#1: 复制
23
说明
(连成的“龙”为atoucheatactactouchoose)
NOIp2000提高组第三题
解题思路:
这题就是dfs暴搜,一开始搜的单词一定是要那个单词开头,并且长度要大于1,然后就是开始暴搜,关键是处理字符串的后缀,然后去对每个串的前缀进行匹配,就行,还有就是要判断每个串不能使用大于2,次,可以用map记录一下。
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
string zf[25];
int n,ans;
map<string,int>M;
void dfs(string s)
{
// cout<<s<<endl;
int len=s.length();
if(len>ans){
ans=len;
}
string a;
for(int i=len-1;i>=1;i--)
{
a+=s[i];
reverse(a.begin(),a.end());//cout<<a<<" "<<s<<endl;
for(int j=1;j<=n;j++)
{
int len1=a.length(),len2=zf[j].length();
if(len1>=len2)continue;
string b;
for(int k=0;k<len1;k++)
b+=zf[j][k];
//cout<<b<<endl;
if(b==a&&M[zf[j]]<2){
string c=zf[j];
c.replace(c.find(a),len1,"");
c=s+c;
M[zf[j]]++;
dfs(c);
M[zf[j]]--;
}
}
reverse(a.begin(),a.end());
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>zf[i];
}
char c;
cin>>c;
ans=0;
for(int i=1;i<=n;i++)
{
if(zf[i][0]==c&&zf[i].length()>1){
M.clear();
M[zf[i]]++;
dfs(zf[i]);
}
}
cout<<ans<<endl;
return 0;
}