1 条题解

  • 0
    @ 2026-2-17 23:28:21
    #include<bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 25; // n≤20,预留足够空间
    string words[MAXN];   // 存储所有单词
    int g[MAXN][MAXN];    // g[i][j]:单词i接单词j的最小合法重合长度,不可接为0
    int used[MAXN];       // 记录每个单词的使用次数,最多2次
    int max_len = 0;      // 记录最长接龙长度
    int n;                // 单词总数
    
    // 预处理:计算所有单词对的最小合法重合长度(保证总长度最大)
    void preprocess()
    {
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                int len_i = words[i].size();
                int len_j = words[j].size();
                // 最大可能的重合长度,必须小于两个单词的长度(避免包含)
                int max_k = min(len_i, len_j) - 1;
                g[i][j] = 0;
                // 【修复】从最小的k开始找,找到第一个匹配的就是最小合法重合长度,总长度最大
                for(int k = 1; k <= max_k; k++)
                {
                    // 取单词i的最后k个字符,和单词j的前k个字符比较
                    string suffix = words[i].substr(len_i - k, k);
                    string prefix = words[j].substr(0, k);
                    if(suffix == prefix)
                    {
                        g[i][j] = k;
                        break; // 找到最小的k就退出,保证总长度最大
                    }
                }
            }
        }
    }
    
    // DFS核心函数
    // cur:当前接龙的最后一个单词索引
    // current_len:当前接龙的总长度
    void dfs(int cur, int current_len)
    {
        // 更新全局最大长度
        max_len = max(max_len, current_len);
    
        // 遍历所有可接的单词
        for(int j = 0; j < n; j++)
        {
            // 合法性校验:单词使用次数<2,且有合法重合长度
            if(used[j] < 2 && g[cur][j] > 0)
            {
                used[j]++; // 标记使用次数+1
                // 递归:新总长度 = 当前长度 + 新单词长度 - 重合长度
                dfs(j, current_len + words[j].size() - g[cur][j]);
                used[j]--; // 回溯,恢复使用次数
            }
        }
    }
    
    int main()
    {
        // 读取单词总数
        cin >> n;
        // 读取n个单词
        for(int i = 0; i < n; i++)
        {
            cin >> words[i];
        }
        // 读取开头字母
        char start;
        cin >> start;
    
        // 预处理单词间的重合长度
        preprocess();
    
        // 初始化所有起点:以start开头的单词
        for(int i = 0; i < n; i++)
        {
            if(words[i][0] == start)
            {
                memset(used, 0, sizeof(used)); // 重置使用次数
                used[i] = 1;                    // 起点单词使用次数+1
                dfs(i, words[i].size());        // 启动DFS
            }
        }
    
        // 输出最长接龙长度
        cout << max_len << endl;
    
        return 0;
    }
    
    • 1

    信息

    ID
    1285
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者