字典树(hdu1075)

hdu1075

  题意:给定一个映射表的关系,给定每个单词的对应的映射的单词。现在给定一段字
符串,要求如果单词能够翻译就进行翻译,否则原样输出,但是注意所有的\n,\r,
空格以及所有的标点符号都是不翻译的。
  思路:先对映射表的单词建立字典树,每个单词的尾节点标记这个单词所映射的单词
的下标,那么对于给定的字符串,我们只要把所有的单词进行解析去字典树中查找即可。

//解法一:建一个映射表和字典树(烧内存,容易超时,但思路简单,用索引值,静态分配)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

const int MAXN = 3010;
const int N = 26;


struct node{
    int index;
    struct node *next[26];
}root;

char word[MAXN][10];
struct node node[MAXN];//这样就不用动态分配了,一开始就开好,然后直接拿来用
int pos;

struct node * newNode()
{
    node[pos].index = -1;
    for(int i = 0 ; i < N ; i++)
        node[pos].next[i] = NULL;
    return &node[pos++];
}

void insert_node(int index, char *str)
{
    int len = strlen(str), i;
    struct node *p = &root;
    for(i = 0; i < len; i++)
    {
        if(p->next[str[i] - 'a'] == NULL)
            p->next[str[i] - 'a'] = newNode();
        p = p->next[str[i] - 'a'];
    }
    p->index = index;//索引值
}

int search_node(char *str)
{
    int len = strlen(str);
    int i;
    struct node *p = &root;
    for(i = 0; i < len; i++)
    {
        if(p->next[str[i] - 'a'] == NULL)
            return -1;
        p = p->next[str[i] - 'a'];
    }
    return p->index;//索引值
}

void solve(char *str)
{
    int len = strlen(str);
    char tmp[MAXN];
    int i = 0;
    while(i < len)
    {
        if(!islower(str[i]))
        {
            printf("%c",str[i]);
            i++;
            continue;
        }
        memset(tmp, 0, sizeof(tmp));
        int j = i;
        int index = 0;
        while(j < len && islower(str[j]))
            tmp[index++] = str[j++];
        int cnt = search_node(tmp);
        if(cnt == -1)
            printf("%s",tmp);
        else
            printf("%s", word[cnt]);
        printf("%c" , str[j]);  //每个单词后面有输入过空格,所以输出这个空格
        i = j + 1;//跳过这个空格继续
    }
    printf("\n");
}

int main()
{
    pos = 0;

    char str[MAXN];
    int index = 0;

    scanf("%s", str);
    getchar();
    while(scanf("%s", word[index]))
    {
        if(strcmp(word[index], "END") == 0)
            break;
        scanf("%s", str);
        getchar();
        insert_node(index++, str);
    }
    scanf("%s%*c" , str);//这样也可以吃回车
    while(cin.getline(str, MAXN))//吃掉了回车
    {
        if(strcmp(str, "END") == 0)
            break;
        solve(str);
    }
    return 0;
}



//解法二:不另外创映射表,将映射表和字典树结合起来,索引值直接改为要索引的字符串
(节约内存,动态分配)

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
#include <ctype.h>
using namespace std;

const int MAXN = 3005;//题目要求最多3000个单词
const int N = 26;


struct node{
    char *s;
    struct node *next[26];
}root;

void insert_node(char *a, char *str)
{
    int len = strlen(str), i;
    struct node *p = &root;
    for(i = 0; i < len; i++)
    {
        if(p->next[str[i] - 'a'] == NULL)
        {
            p->next[str[i] - 'a'] = new struct node;
            p->next[str[i] - 'a']->s = NULL;
            memset(p->next[str[i]-'a']->next,0,sizeof(struct node *)*26);
        }
        p = p->next[str[i] - 'a'];
    }
    p->s = new char [15];//题目要求每个单词最多10个字母
    //p->s = a;// 一开始错在这里,字符串之间赋值要用strcpy,或用string对象
    strcpy(p->s, a);
    //DEBUG
    /*if(p->s != NULL)
            printf("%s",p->s);*/
}

char* search_node(char *str)
{
    int len = strlen(str);
    int i = 0;
    struct node *p = &root;
    for(i = 0; i < len; i++)
    {
        if(p->next[str[i] - 'a'] == NULL)
        {
            return NULL;
        }
        p = p->next[str[i] - 'a'];
    }
    return p->s;//索引
}

void solve(char *str)
{
    int len = strlen(str);
    char tmp[MAXN];
    int i = 0;
    while(i < len)
    {
        if(!islower(str[i]))
        {
            printf("%c",str[i]);
            i++;
            continue;
        }
        memset(tmp, 0, sizeof(tmp));
        int j = i;
        int index = 0;
        while(j < len && islower(str[j]))
            tmp[index++] = str[j++];
        char *cnt = search_node(tmp);
        if(cnt == NULL)
            printf("%s",tmp);
        else
            printf("%s", cnt);
        printf("%c" , str[j]);  //每个单词后面有输入过空格,所以输出这个空格
        i = j + 1;//跳过这个空格继续
    }
    printf("\n");
}

int main()
{
    char str[MAXN];
    char a[MAXN];

    scanf("%s", str);
    getchar();
    while(scanf("%s", a))
    {
        if(strcmp(a, "END") == 0)
            break;
        scanf("%s", str);
        getchar();
        insert_node(a, str);
    }
    scanf("%s%*c" , str);//这样也可以吃回车
    while(cin.getline(str, MAXN))//吃掉了回车
    {
        if(strcmp(str, "END") == 0)
            break;
        solve(str);
    }
    return 0;
}//这里只有一种情况,所以中途不delete//如果是做软件记得用了new后要考虑delete
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值