单词接龙

单词接龙

我竟然有这种勇气把这种题挂出来我也是佩服啊
几个坑:

  • 相同的部分应取最小,所以\(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;
}
posted @ 2018-07-31 10:26  昤昽  阅读(156)  评论(0编辑  收藏  举报