NC16758 [NOIP2000]单词接龙
题目
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入描述
输入的第一行为一个单独的整数n(n ≤ 20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出描述
只需输出以此字母开头的最长的“龙”的长度
示例1
输入
5 at touch cheat choose tact a
输出
23
说明
连成的“龙”为 atoucheatactactouchoose
题解
知识点:DFS。
先要预处理出单词之间互相能衔接的最短长度方便搜索, 表示第 个单词和第 个单词能衔接的最短长度,如果不能衔接则为 ,初始时用 表示可开始的单词;用 表示第 个单词用到几次,两次就不能再用。然后一个简单的搜索,每次更新最大值。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int n; string words[27]; int link[27][27];///x,y单词的衔接长度 int vis[27]; int ans; int check(int x, int y) { for (int i = 1;i < min(words[x].size(), words[y].size());i++) { bool ok = true; for (int j = words[x].size() - i;j < words[x].size();j++) ok &= words[x][j] == words[y][j - (words[x].size() - i)]; if (ok) return i; } return -1; } void dfs(int pos = 0, int sum = 0) { ans = max(ans, sum); for (int i = 1;i <= n;i++) { if (vis[i] == 2 || !~link[pos][i]) continue; vis[i]++; dfs(i, sum + words[i].size() - link[pos][i]); vis[i]--; } } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n; for (int i = 1;i <= n;i++) cin >> words[i]; cin >> words[0]; for (int i = 1;i <= n;i++) for (int j = 1;j <= n;j++) link[i][j] = check(i, j); for (int i = 1;i <= n;i++) link[0][i] = words[0][0] == words[i][0] ? 0 : -1; dfs(); cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16484485.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧