#include 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() > 0) { 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; }