[经典面试题][字典树]字符串唯一前缀问题

题目

一个文件里面有如下字符串
cartefdxh
cart
carlkijfwe
chdfwef
cafkekfld
…………

要从文件中找出唯一能代表该字符串的前缀,然后如下输出
cartefdxh carte
cart cart
carlkijfwe carl
chdfwef ch
cafkekfld caf

以空格分隔…….

思路

用Trie树实现。为每个节点增加一个变量count,用来记录一共有几个字符串使用该字符。找节点计数为1的节点或者叶子节点。

这里写图片描述

代码

    /*---------------------------------------------
    *   日期:2015-02-26
    *   作者:SJF0115
    *   题目: 字符串唯一前缀问题
    *   来源:经典面试题
    *   博客:
    -----------------------------------------------*/
    #include <iostream>
    #include <vector>
    using namespace std;

    #define MAX 26

    struct TrieNode{
        // 有几个字符串公用这个字符
        int count;
        TrieNode *next[MAX];
        TrieNode(){
            count = 0;
            for(int i = 0;i < MAX;++i){
                next[i] = NULL;
            }//for
        }
    };
    // 插入
    void Insert(TrieNode* &root,string str){
        int size = str.size();
        if(size == 0){
            return;
        }//if
        TrieNode *p = root;
        int val;
        for(int i = 0;i < size;++i){
            val = str[i] - 'a';
            if(p->next[val] == NULL){
                p->next[val] = new TrieNode();
            }//if
            // 统计共有几个字符串共用该字符
            p->next[val]->count++;
            p = p->next[val];
        }//for
    }//Insert
    // 字符串的唯一前缀表示
    string OnlyPrefix(TrieNode* root,string str){
        int size = str.size();
        TrieNode *p = root;
        int index = 0,val;
        for(int i = 0;i < size;++i){
            val = str[i] - 'a';
            index++;
            p = p->next[val];
            if(p->count == 1){
                break;
            }//if
        }//for
        return str.substr(0,index);
    }
    // 所有字符串的唯一前缀表示
    vector<pair<string,string> > AllOnlyPrefix(vector<string> strs){
        int size = strs.size();
        pair<string,string> prefix;
        vector<pair<string,string> > vec;
        if(size <= 0){
            return vec;
        }//if
        TrieNode *root = new TrieNode();
        // 创建字典树
        for(int i = 0;i < size;++i){
            Insert(root,strs[i]);
        }//for
        // 唯一前缀
        for(int i = 0;i < size;++i){
            prefix.first = strs[i];
            prefix.second = OnlyPrefix(root,strs[i]);
            vec.push_back(prefix);
        }//for
        return vec;
    }

    int main() {
        vector<string> strs = {"book","boom","cartefdxh","cart","carlkijfwe","chdfwef","cafkekfld"};
        vector<pair<string,string> > vec = AllOnlyPrefix(strs);
        for(int i = 0;i < vec.size();++i){
            pair<string,string> pair = vec[i];
            cout<<pair.first<<"  "<<pair.second<<endl;
        }//for
    }

引用:

[算法系列之二十]字典树(Trie)

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值