1 条题解
-
0
#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
- 上传者