题目
单词接龙是一个与我们经常玩的成语接龙相类似的游戏。
现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”,每个单词最多被使用两次。
在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish ,如果接成一条龙则变为 beastonish。
我们可以任意选择重合部分的长度,但其长度必须大于等于1,且严格小于两个串的长度,例如 at 和 atide 间不能相连。
题解
g[i][j]=k表示单词i到单词j的相同的前后缀最短长度为k。
dfs(string dargon,int i)表示执行到第i个单词时的字符串dargon
word[i].substr(g[last][i])是截取第i个单词从g[last][i]为下标到单词结尾的字串
如at,touch,此时last=0,i=1,则g[0][1]=1,word[1].substr(1)=ouch,拼接完成后就变成atouch。
#include<iostream>
using namespace std;
const int N=25;
int n,g[N][N];
int used[N];
string word[N];
int ans;
void dfs(string dargon,int last){
ans=max((int)dargon.size(),ans);
used[last]++;
for(int i=0;i<n;i++){
if(g[last][i]&&used[i]<2){
dfs(dargon+word[i].substr(g[last][i]),i);
}
}
used[last]--;
}
int main(){
cin>>n;
for(int i=0;i<n;i++)cin>>word[i];
char start;
cin>>start;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
string a=word[i], b=word[j];
for(int k=1;k<min(a.size(),b.size());k++){
if(a.substr(a.size()-k,k)==b.substr(0,k)){
g[i][j]=k;
break;
}
}
}
}
for(int i=0;i<n;i++){
if(word[i][0]==start){
dfs(word[i],i);
}
}
cout<<ans<<endl;
return 0;
}