题目传送门
C++代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 30;
string a[N * 2];
int res; //最大长度
char start; //起始字符
bool st[N * 2];//是否已经使用过
int n;
//两个字符串,最小重叠部分的长度
string merge(string a, string b) {
int n = INF;
//相连接 两层循环找出a的所有可能后缀,然后与b串的前缀进行对比,找到最长的
for (int i = a.size() - 1; i >= 0; i--) { //从后向前,注意起始范围
//i=a.size()-1 i参数准备用于 a.substr(i),就是取后缀,这样就表示取最后一个字符。
string t = a.substr(i);//从i处开始截取,一直截取到结束的意思,即后缀
//这个b.compare用的漂亮,可以避开了b.substr(0,t.size())时超出b的范围的问题。
/* compare
两个字符串相同,返回0。
a字符串小于b字符串,返回-1。
a字符串大于b字符串,返回1。
*/
if (b.compare(0, t.size(), t) == 0) {
n = a.size() - i;
break;
}
}
if (n < INF) return a + b.substr(n);
else return "";
}
//深度优先搜索
//参数1:想要接第几个
//参数2:完成拼接的字符串
void dfs(int step, string tmp) {
//不要求一定要全部使用完,所以随时需要更新结果
if (tmp.size() > res) res = tmp.size();
//如果没有可以尝试的了,需要返回
if (step == 2 * n + 1)return;
//所有的情况尝试一遍
for (int i = 1; i <= 2 * n; i++) {
if (!st[i]) {
string ans = merge(tmp, a[i]);
//找以start为开始字符,并且没有使用过的字符串
if (ans.size()) {
st[i] = true;
dfs(step + 1, ans);
st[i] = false;
}
}
}
}
int main() {
//输入
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
//复制了一份,因为一个字符串最多出现两次
for (int i = n + 1; i <= 2 * n; i++) a[i] = a[i - n];
//龙的开始字符
cin >> start;
//遍历所有以start开头的字符串
for (int i = 1; i <= n; i++)
if (a[i][0] == start) {
st[i] = true;
dfs(1, a[i]);
st[i] = false;
}
//输出最大长度
cout << res << endl;
return 0;
}