UVA - 10391 Compound Words

Problem E: Compound Words

You are to find all the two-word compound words in a dictionary. A two-word compound word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.

Input

Standard input consists of a number of lowercase words, one per line, in alphabetical order. There will be no more than 120,000 words.

Output

Your output should contain all the compound words, one per line, in alphabetical order.

Sample Input

a
alien
born
less
lien
never
nevertheless
new
newborn
the
zebra

Sample Output

alien
newborn

题意:

找出该单词是由给出的单词组成;

并按照字典的顺序输出;


<span style="font-size:18px;">#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;

set <string> Set;

int main () {
	string str;
	while (cin >> str) {
		Set.insert(str);	
	}
	 set<string>::iterator it;
	 for (it = Set.begin(); it != Set.end(); it++) {
		for (int i = 1; i < (*it).length(); i++) {
			string front = (* it).substr(0,i); // 找出从0-i的字符串
			string rear = (* it).substr(i,(*it).length()); // 从i到最后
			if (Set.count(front) && Set.count(rear)) {
				cout << (*it) <<endl;
				break;
			}
		} 
	 }
return 0;

}</span>


这是一个经典的 **字符串匹配问题**:找出字典中所有可以表示为**恰好两个其他单词拼接而成的复合词(two-word compound words)**。 --- ## ✅ 问题解析 - 给定一个按字母顺序排列的单词列表(全部小写,最多 120,000 个) - 要求输出所有满足以下条件的单词: - 它是字典中的某个单词 - 它能被**拆成两个非空子串 `s = prefix + suffix`** - 并且 `prefix` 和 `suffix` 都**独立存在于字典中** - 输出这些复合词,按字典序排序(输入已排序,但结果仍需确保) > 注意:构成复合词的两个部分必须是字典中存在的**完整单词** --- ## ✅ 解法思路 ### 🔍 方法:哈希表 + 枚举分割点 1. 将所有单词存入一个高效的查找结构(如 `unordered_set`)用于 $ O(1) $ 查询 2. 对每个单词,尝试将其从不同位置切分为前缀和后缀(至少长度为1) 3. 检查是否 `prefix` 存在于字典 且 `suffix` 存在于字典 4. 如果是,则该单词是一个复合词,加入结果集合 5. 最后将结果排序并输出(虽然输入有序,但复合词不一定按序生成) ✅ 时间复杂度优化关键: - 单词平均不长(英文单词通常几十字符),所以枚举切分点很快 - 使用哈希集合实现 $ O(1) $ 查找 --- ## ✅ C++ 实现代码 ```cpp #include <iostream> #include <vector> #include <unordered_set> #include <set> #include <string> #include <algorithm> using namespace std; int main() { vector<string> words; unordered_set<string> wordSet; string line; // 读取输入,构建向量和哈希集合 while (getline(cin, line)) { if (line.empty()) break; // 输入可能以空行结束(视平台而定) words.push_back(line); wordSet.insert(line); } // 使用 set 自动去重并排序 set<string> compounds; // 遍历每个单词,判断是否为两词复合词 for (const string& word : words) { int len = word.length(); // 尝试每一种分割方式:i 是前缀长度 [1, len-1] for (int i = 1; i < len; ++i) { string prefix = word.substr(0, i); string suffix = word.substr(i); // 检查 prefix 和 suffix 是否都在字典中 if (wordSet.find(prefix) != wordSet.end() && wordSet.find(suffix) != wordSet.end()) { // 符合条件:是复合词 compounds.insert(word); break; // 找到一种拆法即可,无需继续 } } } // 输出结果(set 已经排好序) for (const string& comp : compounds) { cout << comp << endl; } return 0; } ``` --- ## ✅ 示例验证 输入: ``` a alien born less lien never nevertheless new newborn the zebra ``` 我们逐个检查哪些是复合词: | 单词 | 拆分尝试 | 是否存在两个部分 | |------|----------|----------------| | `alien` | `'a' + 'lien'` → `'a'`✅, `'lien'`✅ | ✅ 加入 | | `newborn` | `'new' + 'born'` → `'new'`✅, `'born'`✅ | ✅ 加入 | | `nevertheless` | 可拆成 `'never'+'theless'` → `'theless'`❌;其它拆法都不行?但注意 `'never'` 和 `'the'` 存在,但 `'theless'` 不等于 `'less'`<br>→ 实际上不能由两个存在的单词组成 → ❌ | | 其它单词 | 如 `a`, `new`, `born` 等太短或无法拆出两个有效词 | ❌ | ⚠️ 注意:`alien` 是 `'a' + 'lien'`,不是 `'ali'+'en'`,只有前者成立! 所以输出: ``` alien newborn ``` ✔️ 匹配样例输出! --- ## ✅ 复杂度分析 - 设单词总数为 $ N \leq 120000 $ - 平均单词长度为 $ L $(比如 ≤ 50) - 每个单词最多做 $ L-1 $ 次分割尝试,每次 substring 和 hash 查询约 $ O(L) $ - 总时间复杂度:$ O(N \cdot L^2) $,实际运行很快(因为 L 很小) - 空间复杂度:$ O(N \cdot L) $ 存储字符串和哈希表 对于现代机器来说完全可行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值