题目描述单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beastbeastbeast 和 astonishastonishastonish ,如果接成一条龙则变为beastonishbeastonishbeastonish ,另外相邻的两部分不能存在包含关系,例如 atatat 和atideatideatide 间不能相连。
输入格式:
输入的第一行为一个单独的整数
n*n (n≤20)
表示单词数,以下n*n
行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.输出格式:
只需输出以此字母开头的最长的“龙”的长度
来源
洛谷P1019鉴定
读题有坑
注意max_初始化
短小精悍(?)的深搜代码:
#include <iostream>
#include <string>
using namespace std;
int n,max_;
string str[20];
int b[20];
int mix(string str1, string str2) {//如果没有重叠部分就返回-1,否则返回重叠部分开始的位置
for(int k=str1.size()-1; k>=0; k--) {//贪心,为了让合并后的字符串尽量长一定要从后往前判断
bool r=1;
int i_2=0;
for(int i=k; i<=str1.size()-1; i++) {
if(!(i_2<=str2.size()-1)) {//判断str2边界
r=0;
break;
} else if(str1[i]!=str2[i_2]) {
r=0;
break;
}
i_2++;
}
if(r) return k;
}
return -1;
}
void search(int cur, string s) {
bool bb=1;//bb规定:0表示有至少一个解,1表示此情况无解
for(int i=0; i<n; i++)
if(b[i]<=1) {//注意每个单词可以用两次
bb=0;
int t=mix(s,str[i]);
if(t!=-1) {
string news;
for(int i=0; i<=t-1; i++)
news+=s[i];
news+=str[i];//合并两个字符串
b[i]+=1;
search(cur+1, news);
b[i]-=1;
}
}
if(bb&&max_<s.size())
max_=s.size();//更新max_
}
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=0; i<=n-1; i++)
cin>>str[i];
char a;
cin>>a;
for(int i=0; i<n; i++)
if(str[i][0]==a) {//枚举每个以字符a开头的字符串
b[i]=1;
string t=str[i];
if(max_<t.size()) {
max_=t.size();//初始化max_
}
search(0, t);//开搜!
b[i]=0;
}
cout<<max_;
return 0;
}