#P3070. 单词接龙(100分)
-
1000ms
Tried: 121
Accepted: 46
Difficulty: 2
所属公司 :
华为od
单词接龙(100分)
题面解释:
在这个单词接龙问题中,给定一个起始单词及一组单词,要求根据特定规则构建一个单词串。规则是:下一个单词的首字母必须与上一个单词的尾字母相同,并且在可选单词中,优先选择长度最长的,若长度相同则选择字典序最小的,已使用的单词不能重复。输入包括一个非负整数K表示起始单词的索引、一个非负整数N表示单词的数量,以及接下来的N个单词。输出是拼接后的单词串。
思路:
数据范围很小,直接按照首字母分类存储每一个字符串然后分别排序,再按照题意拼接即可。
代码说明
-
数据结构:使用
vector<string> g[30]来存储每个首字母对应的单词,数组大小为30,以适应小写字母的情况。 -
输入处理:通过循环输入所有单词,并根据其首字母分类存储。起始单词在读取时单独保存。
-
排序:对每个字母对应的单词使用自定义的比较函数
cmp进行排序,确保我们能够在接龙时快速找到合适的单词。 -
单词接龙:通过一个循环,查找并拼接单词,直到没有可用单词为止。
-
输出结果:最后输出拼接好的单词串。
cpp
#include <bits/stdc++.h>
using namespace std;
// 使用一个二维数组来存储以每个字母开头的单词
vector<string> g[30];
// 自定义比较函数,用于排序
bool cmp(string a, string b) {
// 首先按照长度进行降序排序
if (a.size() != b.size()) return a.size() > b.size();
// 如果长度相同,则按照字典序升序排序
return a < b;
}
int main() {
int id, n; // id是起始单词的索引,n是单词的数量
cin >> id >> n; // 输入起始单词的索引和单词数量
string s; // 存储起始单词
// 输入单词并分类存储
for (int i = 0; i < n; i++) {
string t;
cin >> t; // 输入单词
if (i != id) g[t[0] - 'a'].push_back(t); // 按照首字母分类存储字符串
if (i == id) s = t; // 如果是起始单词,则保存
}
// 对每个首字母分类的单词进行排序
for (int i = 0; i < 26; i++) { // 0到25代表字母a到z
sort(g[i].begin(), g[i].end(), cmp);
}
// 进行单词接龙
while (true) {
int m = s.size(); // 当前字符串长度
int c = s[m - 1] - 'a'; // 获取当前单词的最后一个字母对应的索引
if (g[c].empty()) break; // 如果没有可以接的单词,结束
// 选择首字母与当前单词尾字母相同的第一个单词
s += g[c][0]; // 拼接单词
g[c].erase(g[c].begin()); // 从可选单词中移除已使用的单词
}
cout << s; // 输出最终的单词串
}
python
# 定义比较函数
def cmp(word):
return (-len(word), word) # 返回长度的负值以实现降序排列,字典序保持升序
def main():
# 输入起始单词的索引和单词数量
id = int(input())
n = int(input())
g = [[] for _ in range(26)] # 创建一个二维数组,存储以每个字母开头的单词
s = "" # 存储起始单词
# 输入单词并分类存储
for i in range(n):
t = input().strip() # 输入单词
if i != id:
g[ord(t[0]) - ord('a')].append(t) # 按照首字母分类存储字符串
else:
s = t # 如果是起始单词,则保存
# 对每个首字母分类的单词进行排序
for i in range(26):
g[i].sort(key=cmp) # 使用自定义比较函数进行排序
# 进行单词接龙
while True:
m = len(s) # 当前字符串长度
c = ord(s[m - 1]) - ord('a') # 获取当前单词的最后一个字母对应的索引
if not g[c]: # 如果没有可以接的单词,结束
break
# 选择首字母与当前单词尾字母相同的第一个单词
s += g[c][0] # 拼接单词
g[c].pop(0) # 从可选单词中移除已使用的单词
print(s) # 输出最终的单词串
# 调用主函数
if __name__ == "__main__":
main()
java
import java.util.*;
public class Main {
// 自定义比较器,用于排序
static class WordComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
// 首先按照长度进行降序排序
if (a.length() != b.length()) {
return Integer.compare(b.length(), a.length());
}
// 如果长度相同,则按照字典序升序排序
return a.compareTo(b);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int id = scanner.nextInt(); // 起始单词的索引
int n = scanner.nextInt(); // 单词的数量
List<String>[] g = new ArrayList[26]; // 创建一个列表数组,存储以每个字母开头的单词
// 初始化列表
for (int i = 0; i < 26; i++) {
g[i] = new ArrayList<>();
}
String s = ""; // 存储起始单词
// 输入单词并分类存储
for (int i = 0; i < n; i++) {
String t = scanner.next(); // 输入单词
if (i != id) {
g[t.charAt(0) - 'a'].add(t); // 按照首字母分类存储字符串
} else {
s = t; // 如果是起始单词,则保存
}
}
// 对每个首字母分类的单词进行排序
for (int i = 0; i < 26; i++) {
Collections.sort(g[i], new WordComparator()); // 使用自定义比较器进行排序
}
// 进行单词接龙
while (true) {
int m = s.length(); // 当前字符串长度
int c = s.charAt(m - 1) - 'a'; // 获取当前单词的最后一个字母对应的索引
if (g[c].isEmpty()) break; // 如果没有可以接的单词,结束
// 选择首字母与当前单词尾字母相同的第一个单词
s += g[c].get(0); // 拼接单词
g[c].remove(0); // 从可选单词中移除已使用的单词
}
System.out.println(s); // 输出最终的单词串
}
}
题目内容
单词接龙的规则是:
- 可用于接龙的单词首字母必须要前一个单词的尾字母相同;
- 当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。
现给定一组全部由小写字母组成单词数组,并指定其中的一个单词作为起始单词,进行单词接龙,
请输出最长的单词串,单词串是单词拼接而成,中间没有空格。
输入描述
- 输入的第一行为一个非负整数,表示起始单词在数组中的索引K,0<=K<N ;
- 输入的第二行为一个非负整数,表示单词的个数N;
- 接下来的N行,分别表示单词数组中的单词
输出描述
- 输出一个字符串,表示最终拼接的单词串。
备注
- 单词个数N的取值范围为[1,20];
- 单个单词的长度的取值范围为[1,30];
样例1
输入
0
6
word
dd
da
dc
dword
d
输出
worddwordda
说明
先确定起始单词word,再接以d开头的且长度最长的单词dword,剩余以d开头且长度最长的有dd、da、dc,则取字典序最小的da,所以最后输出worddwordda。
样例2
输入
4
6
word
dd
da
dc
dword
d
输出
dwordda
说明
先确定起始单词dword,剩余以d开头且长度最长的有dd、da、dc,则取字典序最小的da,所以最后输出dwordda。