UVa 10391 - Compound Words

题目链接:

UVa: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=1332

zoj :  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=825


类型: 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)的时间判断一个单词是否属于字典。 



/*
 * 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';
            if(search(str) && search(word[i]+j+1)){
                puts(word[i]); break;
            }
        } 
    }
    return 0;
}

——  生命的意义,在于赋予它意义。

 

          
     原创 http://blog.csdn.net/shuangde800 , By   D_Double  (转载请标明)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值