当前位置:软件学习 > Word >>

UVa 10391 - Compound Words


类型: Hash

原题:
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


题目大意:
题目很短很简洁,大爱~! 
给出一系列按字典序排好的单词, 把它们看成是一个字典。然后再按字典序输出里面所有的复合词,复合词就是这个单词是由字典中的另外两个单词组成的。

思路与总结:
很自然地可以想到一个思路,就是按顺序直接枚举每一个单词,然后判断这个单词是不是复合词,是的话就输出。
这题的核心就在于怎样判断一个单词是否是复合词,由复合词的定义,可以把单词拆分成两个,枚举一个单词的所有拆分方案,然后再判断是否有拆分的两个单词是否在字典中即可。
题目数据量达到120,000, 所以一定要找到一个快速的判断一个单词是否属于字典集合中的方法。
这是哈希表的超高速作用就凸显出来了。只要给每个单词建立哈希表映射关系, 然后就可以几乎可以是O(1)的时间判断一个单词是否属于字典。


[cpp] 
/*
 * UVa  10391 - Compound Words
 * 哈希表
 * Time: 0.020s (UVa)
 * Author: D_Double
 */ 
#include<iostream>   
#include<cstdio>   
#include<cstring>   
#define MAXN 120003 
using namespace std;   
typedef char Word[30]; 
 
 
Word word[MAXN]; 
const int HashSize = MAXN; 
int N, head[HashSize], next[HashSize]; 
 
inline void init_lookup_table(){ 
    N=1;   
    memset(head, 0, sizeof(head)); 

 
inline int hash(char *str){ // 字符串哈希函数 
    int seed = 131; 
    int hash=0; 
    while(*str) hash = hash * seed + (*str++); 
    return (hash & 0x7FFFFFFF) % HashSize; 

 
int add_hash(int s){ 
    int h = hash(word[s]); 
    int u = head[h]; 
    while(u) u = next[u]; 
    next[s] = head[h]; 
    head[h] = s; 
    return 1; 

 
int search(char *s){ 
    int h = hash(s); 
    int u = head[h]; 
    while(u){ 
        if(strcmp(word[u], s)==0) return u; 
        u = next[u]; 
    } 
    return 0; 

 
int main(){ 
    Word str; 
    N = 1; 
    init_lookup_table(); 
    while(gets(word[N])){ 
        add_hash(N); 
        ++N; 
    } 
    // 查询 
    for(int i=1; i<N; ++i)if(word[i][1]){ 
        for(int j=0; j<strlen(word[i])-1; ++j){ 
            strcpy(str, word[i]); 
            str[j+1] = '\0'; www.zzzyk.com
            if(search(str) && search(word[i]+j+1)){ 
                puts(word[i]); break; 
            } 
        }  
    } 
    return 0; 


作者:shuangde800
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,