【ICPC-346】uva 10282 - Babelfish

点击打开链接

 

题目意思:  给定很多组单词,每一组有两个单词,后面一个单词匹配前面一个单词,现在要求每输入一个单词就去判断是否有对应的单词,有输出对应的单词,否则输出eh

 

解题思路: 

 

                                                       1 哈希表查找

                      哈希表映射可以比map快很多,还有选择的哈希函数应该尽量满足每一个状态对应一个整数值,这样冲突比较少,但是为了处理冲突,  我么利用链表的思想,将相同key值的状态放在一个链表里面,所以哈希函数的选择很重要,见我的博客就有常见的字符串哈希函数。
                      大概的思想:每一次读入两个字符数组也就是一下说的状态去求哈希值,然后插人哈希表中,插入的时候是采用往前插,即每一次都要把链表指针往后指,然后更新表头。(哈希表其实就是一个大的数组,得到的哈希值作为数组的下标,然后数组存储的第几个状态这样我么通过“哈希值key-数组-状态”这种思想就可以得到解了)

 

代码:

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <map>
using namespace std;
#define MAXN 1000003//哈希表的长度

typedef char word[25];//定义状态的类型为char数组
word Dic[MAXN] , For[MAXN];//两种不同的状态存放进去,数组的每一个元数就是一个char 数组
int head[MAXN] , next[MAXN];//head是表头,next是链表
char ch[25];
int  cnt;//记录第几个状态

//哈希函数 
int Hash(char *str)  
{  
    int hash = 0;  
    while (*str) hash = (*str++) + (hash << 6) + (hash << 16) - hash;  
    return (hash & 0x7FFFFFFF) % MAXN;  
}  

//插入哈希表中
void insert_table(int s){
    int h = Hash(For[s]);//对For[s]这个状态求哈希值
    next[s] = head[h];//将链表往后移动一位
    head[h] = s;//插入表头中
}

//哈希映射
int Hash_map(char *str){
    int h = Hash(str);
    int u = head[h];//从表头开始查找链表
    while(u){
        if(strcmp(str , For[u]) == 0){//如果找到了直接返回
            printf("%s\n" , Dic[u]) ; return 1;
        }
        u = next[u];//指针指向下一个
    }
    return 0;
}

int main(){
    //freopen("input.txt" , "r" , stdin);
    int i , j , flag;
    char str[25];
    cnt = 1;//不用0,由于被看做不存在
    while(gets(ch) && ch[0] != '\0'){
        i = j = flag = 0;
        for(int k = 0 ; k < strlen(ch) ; k++){
            if(ch[k] == ' '){ 
                flag = 1 ; continue;
            }
            if(!flag){ 
                Dic[cnt][i] = ch[k] ; i++;
            }
            if(flag){ 
                For[cnt][j] = ch[k] ; j++;
            }
        }
        insert_table(cnt);//插入
        cnt++;//这里不要忘了
    }
    while(gets(str)){
        if(!Hash_map(str)) printf("eh\n");
    }
}

                                                   2 map映射

1  map 由于每组的dictionary都不同可以利用map的性质去映射查找,但是由于map的内部实现是红黑数,加上如果用string做键值,那么处理起来将会很慢,但是代码简单
2  注意判断空格,直接判断ch[0] != '\0';

 

代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <map>
using namespace std;
#define MAXN 100010

map<string , string>m;
string str1 , str2 , str;
char ch[100];

int main(){
    //freopen("input.txt" , "r" ,stdin);
    m.clear();
    int flag , cnt = 1;
    while(gets(ch) && ch[0] !='\0'){
        str1 = str2 = "" ; flag = 0;
        for(int i = 0 ; i < strlen(ch) ; i++){
            if(ch[i] == ' ') { flag = 1 ; continue;}       
            if(flag) str2 += ch[i];
            if(!flag) str1 += ch[i];
        }
        m[str2] = str1;//插入
    }
    
    while(cin>>str){
        if(m[str] != "") cout<<m[str]<<endl;
        else printf("eh\n");
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值