题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1247
Hat’s Words
Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18060 Accepted Submission(s): 6428
Problem Description
A hat’s word is a word in the dictionary thatis the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.
Input
Standard input consists of a number oflowercase words, one per line, in alphabetical order. There will be no morethan 50,000 words.
Only one case.
Output
Your output should contain all the hat’swords, one per line, in alphabetical order.
Sample Input
a
ahat
hat
hatword
hziee
word
Sample Output
ahat
hatword
-----------------------------------------------------
思路
题意:已知一个字典,按字典顺序输出所有可以由字典中两个单词(两个单词可以相同)拼接成的单词。
算法:用数组存储所有单词,随机存取为O(1);用map的keySet存储单词,valueSet用0/1表示该单词否/是在词典中出现,C++ STL里map用红黑树实现,查询一个单词是否在map中为O(logN), 其中N为map中单词总数。其实只要把单词装到数组里再二分查找也是O(logN), 不过可能用map方便一点吧,占内存倒是真的。
用数组遍历单词,枚举所有拆分的可能性,如果拆分的两个单词都在map中查到了,则输出。
千万注意一个单词可能有多种可能的拆分方式,但只能输出一次。
字典树是一种更高效的做法,但用简单的map也能通过了。
-----------------------------------------------------
代码
#include<fstream> #include<iostream> #include<string> #include<map> using namespace std; const int NMAX = 50055; string s[NMAX] = {}; map<string,int> mp; int main() { #ifndef ONLINE_JUDGE ifstream fin ("hdu1247.txt"); int i = 0,j,t; string ss,s1,s2; while (fin >> ss) { s[i] = ss; mp[ss] = 1; i++; } for (j=0; j<i; j++) { for (t=1; t<=s[j].size()-1; t++) { s1 = s[j].substr(0,t); s2 = s[j].substr(t); if (mp[s1] && mp[s2]) { cout << s[j] << endl; break; } } } return 0; #endif #ifdef ONLINE_JUDGE int i = 0,j,t; string ss,s1,s2; while (cin >> ss) { s[i] = ss; mp[ss] = 1; i++; } for (j=0; j<i; j++) { for (t=1; t<=s[j].size()-1; t++) { s1 = s[j].substr(0,t); s2 = s[j].substr(t); if (mp[s1] && mp[s2]) { cout << s[j] << endl; break; } } } #endif }