原本应该不是一道难题,因为奇特的理解wa了三次,记录一下。
题目要求最长的龙,有以下几点需要注意:
1.单词可以使用两次,因此存在自己连接自己的情况,不要想当然的。
2.后缀与前缀的公共部分取最小。
3.重叠部分不能存在包含关系。
解决办法还是比较好想的,对两两单词的连接部分进行预处理(注意自己和自己),然后使用深度搜索,对每个可行答案进行判断。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include <stack>
#define LL long long
using namespace std;
const int N = 1e6 + 10;
int vis[30],chk[21][21],n,ans=0;
string s[21];
char m;
int ll(int a,int b){
int la=s[a].length(),lb=s[b].length();
int len=min(la,lb);
for(int i = 1; i < len; i++) {//重叠长度从1开始,直到最短的字符串长度-1(因为不能包含)
int flag = 1;
for(int j = 0; j < i; j++)
if(s[a][la - i + j] != s[b][j]) flag = 0;
if(flag) return i;//检测完毕相等则立即return
}
return 0;
}
void check(){
int len1,len2;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
chk[i][j]=ll(i,j);
//cout<<chk[i][j]<<' ';
}
}
}
void dfs(int k,int len){
int l=0;
for(int i=1;i<=n;i++){
if(vis[i]<2&&chk[k][i]>0){
vis[i]++;
dfs(i,len+s[i].length()-chk[k][i]);
vis[i]--;
}
}
ans=max(ans,len);
return ;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
}
cin>>m;
check();
for(int i=1;i<=n;i++){
if(m==s[i][0]) {
vis[i]++;
dfs(i,s[i].length());
vis[i]--;
}
}
cout<<ans;
return 0;
}