https://www.luogu.org/problemnew/show/P1019
#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define F(a,b) for(int a=1;a<=b;a++)
#define LEN 30
using namespace std;
string tr[LEN];//存储字符串
int yc[LEN][LEN];//yu chuli 两个字母的最小重叠部分
int n;
char ch;//开头字母
int vis[LEN];
int an=0;//每次搜索到的最长串
int ans=0;
void dfs(int p){//以p编号单词为尾部
bool jx=false;
F(i,n){ //遍历所有单词序列
if(vis[i]>=2) continue;//最多使用两次
if(yc[p][i]==0) continue;//两个单词没有重合部分
if(yc[p][i]==tr[p].size() ||
yc[p][i]==tr[i].size()) continue;//有包含关系
an += (tr[i].size()-yc[p][i]);//两单词合并再减去最小重合部分
vis[i]++;//使用了一次
jx=true;
dfs(i);
an -= (tr[i].size()-yc[p][i]);//两单词合并再减去最小重合部分
vis[i]--;
}
if(jx==false){//说名没有任何一个单词可以相连,走到了递归尽头
ans=max(ans,an); //更新ans
}
}
//min together
int mt(int x,int y){ //mt函数, 返回x单词后y的最小重叠部分
for(int i=tr[x].size()-1;i>=0;i--){//从尾部向前扫描
int iy=0;
bool fd=true;
for(int ix=i;ix<tr[x].size();ix++){
if(tr[x][ix]!=tr[y][iy++]){
fd=false;
break;
}
}
if(fd==true){
return tr[x].size()-i;
}
}
return 0;
}
int main(){
// freopen("./in","r",stdin);
cin>>n;
F(i,n){
cin>>tr[i];
}
cin>>ch;
F(i,n)F(j,n){ //预处理yc
yc[i][j]=mt(i,j);
}
int i=0;
F(i,n){//从头到尾看一下有没有指定字母开头的单词
if(tr[i][0]==ch){
vis[i]++;
an=tr[i].size();
dfs(i);
vis[i]--;
}
}
cout<<ans;
return 0;
}