每日一题·648.单词替换·前缀树

题目

示例

 

思路

前缀:字符串的前缀是指字符串的任意首部。比如字符串“abbc”的前缀有“a”,“ab”,“abb”,“abbc”。
前缀树:前缀树是一种用于快速检索的多叉树结构,利用字符串的公共前缀来降低查询时间,核心思想是空间换时间,经常被搜索引擎用于文本词频统计。前缀树多用于字符串。
思路
将本题dictionary转换为前缀树,然后对sentence遍历,判断字符串前缀是否位于树上,存在就进行简化输出,不存在就完全输出,最后定义的字符串链接所有结果的比较结果
以下代码还可以优化

代码

//0:结束,1:没有结束
typedef struct word{
    int end;
    struct word * next[26];
}word;

/* 1:表示未结束  0:表示结束*/
word * trieCreate(){
    word * obj = malloc(sizeof(word) * 1);
    for(int i = 0; i < 26; i++)
    {
        obj->next[i] = NULL;
    }
    obj->end = 0;;
    return obj;
}
/*
*void trieInsert(Trie* obj, char * word)
void trieInsert:向前缀数插入字符串
Trie* obj:前缀树头结点
char * word:字符串
返回值:无
*/
void word_create(word * root, char ** dictionary, int inode)
{
    int len = strlen(dictionary[inode]);
    for(int i = 0; i < len; i++)
    {
        if(root->next[dictionary[inode][i] - 'a'] == NULL)
        {
            word * n = trieCreate();
            root->next[dictionary[inode][i] - 'a'] = n;
        }
        root = root->next[dictionary[inode][i] - 'a'];
    }
    root->end = 1;
}
/*
*char * str_if(word * root, char * sentence, int len_left, int len_right)
char * str_if:判断字符串前缀是否在前缀树上
word * root:前缀树头结点
char * sentence:比较字符串
int len_left:比较字符串的左节点
int len_right:比较字符串的右节点
返回值:存在就输出存在部分,不存在就不简化输出
*/
char * str_if(word * root, char * sentence, int len_left, int len_right)
{
    int len = 0;
    for(int i = len_left; i < len_right; i++)
    {
        if(root->next[sentence[i] - 'a'] && root->end == 0)
        {
            len++;
            root = root->next[sentence[i] - 'a'];
        }
        else
        {
            if(root->end == 0)
            {
                len = len_right - len_left;
            }
            break;
        }
    }
    if(len)//简化
    {
        char * str = malloc(sizeof(char) * (len + 1 + 1));
        strncpy(str, sentence+len_left, len);
        str[len] = ' ';
        str[len + 1] = '\0';
        return str;
    }
    else//不简化,代码还可以优化
    {
        char * str = malloc(sizeof(char) * (len_right - len_left + 1 + 1));
        strncpy(str, sentence+len_left, len_right - len_left);
        str[len_right - len_left] = ' ';
        str[len_right - len_left + 1] = '\0';
        return str;
    }
    return NULL;
}
/*
*char * replaceWords(char ** dictionary, int dictionarySize, char * sentence)
char * replaceWords:将字符串根据字典进行优化
char ** dictionary:字典
int dictionarySize:字典行数
char * sentence:字符串
返回值:优化后的字符串
*/
char * replaceWords(char ** dictionary, int dictionarySize, char * sentence){
    char * str = malloc(sizeof(char) * (1000 * 1000 + 1));
    str[0] = '\0';
    word * root = trieCreate();
    for(int i = 0; i < dictionarySize; i++)
    {   
        word_create(root, dictionary, i);
    }
    int len = strlen(sentence);
    int len_left = 0;
    int i;
    for(i = 0; i < len; i++)
    {
        if(sentence[i] == ' ')
        {
            strcat(str , str_if(root, sentence, len_left, i));

            len_left = i+1;
        }
    }
    strcat(str , str_if(root, sentence, len_left, i));
    len = strlen(str);
    str[len - 1] = '\0';
    trieFree(root);
    return str;
}
//销毁前缀树
void trieFree(word * obj) {
    for(int i = 0; i < 26; i++)
    {
        if(obj->next[i])
            trieFree(obj->next[i]);
    }
    free(obj);
}

时间空间复杂度

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值