单词接龙
单词接龙
我竟然有这种勇气把这种题挂出来我也是佩服啊
几个坑:
- 相同的部分应取最小,所以\(easta,astab\)的重叠部分是\(a\)
- “包含”是在最小意义下的包含,如\(beate,eate\)并不包含,因为其最小重叠部分是\(e\)
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 20 + 1;
string w[MAXN];
int vis[MAXN], dist[MAXN][MAXN];
int get(int from, int to)
{
// w[from]->w[to]:abcd->cdef
const int m = w[from].size(), n = w[to].size();
string a = w[from], b = w[to];
int l, r = min(m, n);
for (l = 1; l <= r; l++) {
if (a.substr(m - l, l) == b.substr(0, l)) break;
}
if (l >= r) return 0;
return l;
}
int dfs(int from, int x, int n)
{
vis[x]++;
int ans = w[x].size();
if (from != -1) ans -= dist[from][x];
int l = 0;
for (int i = 0; i < n; i++)
{
if (!dist[x][i] or vis[i] > 1) continue;
int m = dfs(x, i, n);
l = max(l, m);
}
vis[x]--;
return ans += l;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> w[i];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
dist[i][j] = get(i, j);
}
char Begin;
cin >> Begin;
int ans = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++)
{
if (w[i][0] == Begin)
{
int l = dfs(-1, i, n);
if (l > ans) ans = l;
}
}
cout << ans;
return 0;
}