Hat’s Words
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8030 Accepted Submission(s): 2905
Problem Description
A hat’s word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.
You are to find all the hat’s words in a dictionary.
Input
Standard input consists of a number of lowercase words, one per line, in alphabetical order. There will be no more than 50,000 words.
Only one case.
Only one case.
Output
Your output should contain all the hat’s words, one per line, in alphabetical order.
Sample Input
a ahat hat hatword hziee word
Sample Output
ahat hatword
给你一写单词,判定哪些单词可以由这本字典里的其他两个或者两个以上的单词组成。
题目分折:
首先构造字典树,在字典树里只标识哪些单词是存在的,(不考虑前缀的多少了)。对于每一个单词,依照前缀单词 将单词分割,最后从后往前判定,最后的一部分是否被包含在 这本字典的前缀单词中即可。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1247
小乐一下:
字典树能够解决的一些问题:
1,统计前缀个数。
2,判定一个单词是否可以由某些前缀组成(本题)
3,统计字典树结点个数(只要在 InsertTrie() 里加一个全局变量,创造结点 +1 即可)
4,快速检索,查找生词(这正是体现了字典树的检索功能)
5,串排序(非常快,但我还没能解决输出,虽说只要是 前序遍历)请指教。
6,递推的优化。(文章解密一题,还没有解决)
7,最长公共前缀(还没有解决) 这些问题,待解决时会一起奉上。
代码:
#include<cstdio>
#include<cstring>
#include<malloc.h>
typedef struct TrieNode{
int x;
struct TrieNode * next[26];
}*Trie;
Trie Root;
char str[50010][20];
void InitTrie(Trie &pRoot){pRoot = NULL;}
Trie CreateTrie(){
Trie p = (Trie)malloc(sizeof(struct TrieNode));
for(int i = 0;i<26;i++) p->next[i] = NULL;
p->x = 0;
return p;
}
void InsertTrie(Trie &pRoot,char *s){
Trie p;
int i,k;
if(!(p=pRoot)) p = pRoot = CreateTrie();
i = 0;
while(s[i]){
k = s[i++] - 'a';
if(!(p->next[k])) p->next[k] = CreateTrie();
p = p->next[k];
}
p->x = 1; //这个前缀单词是存在的。
}
bool SearchTrie(Trie &pRoot,char *s){
int i,k,top;
Trie p = pRoot;
int st[1010];
i = 0;top = 0;
while(s[i]){
k = s[i++]-'a';
//if(p->next[k]==NULL) return false;
p = p->next[k];
if(p->x && s[i]) st[top++] = i; //将一个单词分割成几个部分。
}
while(top){ //从后面往前面试探,如果后面的能够在字典树里 找到 存在的前缀单词,那么这个 单词是符合题意的。
bool ok = true;
p = pRoot;
i = st[--top];
while(s[i]){
k = s[i++] - 'a';
if(p->next[k] == NULL) {ok = false;break;}
p = p->next[k];
}
if(p->x && ok) return true;
}
return false; //可以看出,如果只是前缀,那么 top不会自加,因为 s[i] == '\n',而直接返回 false;
}
int main(){
int cnt = 0;
while(scanf("%s",str[cnt])!=EOF){
InsertTrie(Root,str[cnt]);
cnt++;
}
for(int i = 0;i<cnt;i++){
if(SearchTrie(Root,str[i])) printf("%s\n",str[i]);
}
return 0;
}
伟大的梦想成就伟大的人,从细节做好,从点点滴滴做好,从认真做好。