#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int N = 25, maxm = 1e5 + 10;
int n;
string s[N];
string str, ptr, ans;
int h[N * N], e[N * N], ne[2 * N * N], idx;
int st[N * N];
vector<int>q;
int maxi = 0;
int g[N][N];
void DFS(int num, int len);
void add(int a, int b);
int kmp(string s1, int len1, string s2, int len2);
void cal_next(string s1, int* next, int len);
void test();
int MaxLenth(string s);
int MaxLenth(string s) // 有时候要允许自环的存在,因此这个函数是为了记录相同的字符串前后缀的最小值
{
int i = 0, j = s.size() - 1;
string s1, s2;
s1 = s2 = "";
while (i < s.size() - 1)
{
if (s1 == s2)
{
if (s1.empty())
{
s1 += s[i], s2 += s[j];
i++, j--;
}
else
{
//cout << s1 << " " << s2 << endl;
return i;
}
}
else
{
s1 += s[i];
string temp = "";
temp += s[j];
temp += s2;
s2 = temp;
i++, j--;
}
}
return 0;
}
void add(int a, int b) // 邻接矩阵法建立有向边
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
void DFS(int num, int len)
{
//if (st[num] > 2)
//{
// //cout << num << " ";
// maxi = max(maxi, len);
// return;
//}
if (g[num][num] > 0) // 如果有自环首先迭代自环
{
st[num]++;
if(st[num] <= 2) DFS(num, len + s[num].size() - g[num][num]); // 如果当前字符串已经被使用两次将不会再迭代
st[num]--;
}
for (int i = h[num]; i != -1; i = ne[i]) // 从邻接表中选择元素
{
st[e[i]]++;
if(st[e[i]] <= 2) DFS(e[i], len - g[num][e[i]] + s[e[i]].size()); // 更新长度以及进入的单词编号
st[e[i]]--;
}
maxi = max(maxi, len);
}
void cal_next(string s1, int* next, int len)
{
next[0] = next[1] = 0; // next[0]和next[1]都初始化为0
for (int i = 1; i < len; ++i) // 从第二个字符开始遍历模式串
{
int j = next[i]; // 从当前位置的前一个next值开始匹配
while (j && s1[i] != s1[j]) // 如果不匹配且j不为0,则回退到next[j]
j = next[j];
next[i + 1] = (s1[j] == s1[i]) ? j + 1 : 0; // 如果匹配,则next[i+1]为j+1,否则为0
}
}
int kmp(string s1, int len1, string s2, int len2) // 计算不同字符串之间的前后缀值
{
int next[maxm];
cal_next(s1, next, len1);
int j = 0;
for (int i = 0; i < len2; i++)
{
while (j && s1[j] != s2[i]) j = next[j];
if (s1[j] == s2[i]) ++j;
}
return j;
}
void test()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
cout << g[i][j] << " ";
cout << endl;
}
}
int main()
{
memset(h, -1, sizeof h);
cin >> n;
for (int i = 1; i <= n; i++) cin >> s[i];
char c;
cin >> c;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int plen = s[i].size(), slen = s[j].size();
if (i != j)
{
g[j][i] = kmp(s[i], plen, s[j], slen); // 判断两个字符串是否首尾相连,并把长度计算出来
g[i][j] = kmp(s[j], slen, s[i], plen);
if (g[i][j]) add(i, j); // 建立一条有向边
if (g[j][i]) add(j, i);
}
else
{
g[i][j] = MaxLenth(s[i]);
}
}
}
for (int i = 1; i <= n; i++)
if (s[i][0] == c) q.push_back(i); // 判断输入的字符串第一个字母是否等于指定字母,若相等则可以作为第一个单词
for (auto p : q)
{
st[p]++;
if(st[p] <= 2) DFS(p, s[p].size());
st[p]--;
}
cout << maxi << endl;
//test();
return 0;
}