【C++心路历程32】【NOIP2000】单词接龙【图论爆搜最长链】

本文介绍了如何使用C++解决单词接龙问题,通过转化为图论中的最长路径来寻找以特定字母开头的最长单词链。文章提供了一个样例输入和输出,并讨论了两种解决方案,包括暴力枚举和图论方法,其中图论方法更优,能在n^2的时间复杂度内完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题描述】

  单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母(不是单词),请你计算以这个字母开头的长度最长的“龙”,每个单词最多在“龙”中出现两次。
  要注意的是,两个单词接龙规则如下:
  1、如果第一个单词的后面的连续若干字母与第二个单词前面的连续若干字母依次相同,则这两个单词可以接龙,例如 beast 和 astonish ,如果接成一条龙则变为 beastonish。
  2、两个单词接成一条龙后,龙的长度要比两个单词的长度都长。例如单词 at 和 atide 接成一条龙后为atide,龙的长度与第二个单词相同,所以这两个单词不能接龙。而单词ababab和ababab,可以接成ababababab,但不能为ababab。
  3、接龙时,如果两个单词接龙后的单词有多种情况,要尽可能保证接龙后龙的长度最长。例如cabab和ababc,一定要接成cabababc,为而不是cababc。

【输入格式】

  输入的第一行为一个单独的整数n 表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

【输出格式】

  只需输出以此字母开头的最长的“龙”的长度

【输入样例】

5
at
touch
cheat
choose
tact
a

【输出样例】

23

【样例解释】

  最长的接龙是下面几个单词进行:
    at -> touch -> cheat -> tact -> tact -> touch -> choose
  连成长度为23的“龙”: atoucheatactactouchoose

【数据范围】

  50%的数据有:n<=5;
  100%的数据有:n<=10,每个单词的长度不超过40。
【分析】
1、暴力枚举各个单词的排列,并计算长度取最大值 .O(n!)
2、可以转化为图论,求有向图最长路径。在n^2的时间复杂度内连边单词,对于单词(a,b),边权为b的长度减去a,b重合长度,这样即可转化为一张有向图。 对于最后的起首字母做相同处理即可。
实现技巧:当然可以每个单词复制一遍࿰

### NOIP 2000 单词接龙问题的 Python 实现 单词接龙问题是经典的图论问题之一,通常可以通过构建邻接关系并利用广度优先索 (BFS) 或深度优先索 (DFS) 来解决。以下是针对该问题的具体解题思路以及完整的 Python 实现。 #### 解题思路 1. **建模**:将每个单词视为节点,如果两个单词可以首尾相连,则它们之间存在一条边。这样就形成了一个无向图。 2. **输入处理**:读取所有单词,并建立字典来存储可能的连接关系。 3. **算法选择**:由于题目要求找到最长路径而非最短路径,因此采用 DFS 进行遍历更为合适。通过回溯记录当前路径长度的最大值。 4. **剪枝优化**:为了避免不必要的计算,在每次扩展时仅考虑尚未访问过的单词,从而减少重复操作。 具体实现如下: ```python from collections import defaultdict, deque def word_chain(words): # 构造字母到单词列表映射 letter_to_words = defaultdict(list) for word in words: letter_to_words[word[-1]].append(word) max_length = 0 visited = set() def dfs(current_word, length): nonlocal max_length max_length = max(max_length, length) last_char = current_word[-1] candidates = letter_to_words[last_char] for next_word in candidates[:]: if next_word not in visited and next_word[0] == last_char: visited.add(next_word) dfs(next_word, length + 1) visited.remove(next_word) for start_word in words: if start_word not in visited: visited.add(start_word) dfs(start_word, 1) visited.remove(start_word) return max_length # 输入样例 if __name__ == "__main__": n = int(input().strip()) words = [] for _ in range(n): words.append(input().strip()) result = word_chain(words) print(result) ``` 上述代码实现了基于 DFS 的单词接龙求解方法[^1]。其中 `word_chain` 函数负责核心逻辑部分,而辅助数据结构如哈希表用于加速查找过程。 #### 关键点说明 - 使用了 `defaultdict` 存储以某个字符结尾的所有单词集合,便于快速定位候选者。 - 定义了一个全局变量 `max_length` 记录最大链长,并在递归过程中不断更新其值。 - 对于每一个未被使用的起始单词调用一次深函数尝试延展链条直至无法继续为止。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值