题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish,如果接成一条龙则变为 beastonish,另外相邻的两部分不能存在包含关系,例如 at 和 atide 间不能相连。
输入格式
输入的第一行为一个单独的整数
n 表示单词数,以下
n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出格式
只需输出以此字母开头的最长的“龙”的长度。
#include<bits/stdc++.h>
#define gc ch=getchar()
#define ps puts("")
#define pc putchar(32)
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e3+10;
template <class T>void read(T &s){
s=0;T f=1;char gc;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;gc;}
while(ch<='9'&&ch>='0'){s=s*10+ch-'0';gc;}
s*=f;
}
template <class T>void put(T s){
if(s<0)s=-s,putchar('-');
if(s>9)put(s/10);
putchar(s%10+'0');
}
int ans=-INF;//最终答案串的长度;
string words[N];//记录单词;
string start;
int max(int a,int b){
if(a>b) return a;
else return b;
}
int use[N];//一个单词最多被使用两次
int n;
bool check(string a,string b,int len){//判断b是否能作为最长接续字符串;
//len为接口(重合)长度(从1 开始枚举)
int lens=a.length();
for(int i=0;i<len;i++){
if(a[lens-len+i]!=b[i])//头串末尾与尾串开头进行比较,
return false;
}
return true;//对比成功,这个长度可以接续
}
void addstring(string &a,string b,int len){
int lens=b.length();
for(int i=len;i<lens;i++)
a+=b[i]; //cpp 字符串特性,取地址 直接拼接字符;
}
void dfs(string str){
int lens=str.length();
ans=max(ans,lens);//更新答案串长度;
for(int i=1;i<=n;i++){
if(use[i]>=2) continue;
int maxnlens=words[i].length();
//最大的重合长度 我们要使得它尽可能小->从小枚举看看能否接续
for(int j=1;j<=maxnlens;j++){
if(check(str,words[i],j)){
//如果能接,就接看看
string temp=str;
addstring(temp,words[i],j);
if(temp.length() == str.length()) continue;
//长度没变 加个屁;
use[i]++;
dfs(temp);
//如果加了 就从新串开始尝试拼接
use[i]--;
//回溯
}
}
}
}//dfs搜索结果
int main(){
memset(use,0,sizeof(use));
read(n);
for(int i=1;i<=n;i++)
cin>>words[i];
cin>>start;
dfs(start);
put(ans);
return 0;
}