1032. 字符流(每日一难phase2--days28)

1032. 字符流

设计一个算法:接收一个字符流,并检查这些字符的后缀是否是字符串数组 words 中的一个字符串。

例如,words = [“abc”, “xyz”] 且字符流中逐个依次加入 4 个字符 ‘a’、‘x’、‘y’ 和 ‘z’ ,你所设计的算法应当可以检测到 “axyz” 的后缀 “xyz” 与 words 中的字符串 “xyz” 匹配

按下述要求实现 StreamChecker 类:

  • StreamChecker(String[] words) :构造函数,用字符串数组 words 初始化数据结构
  • boolean query(char letter):从字符流中接收一个新字符,如果字符流中的任一非空后缀能匹配 words 中的某一字符串,返回 true ;否则,返回 false。

示例:

输入: [“StreamChecker”, “query”, “query”, “query”, “query”, “query”,
“query”, “query”, “query”, “query”, “query”, “query”, “query”]
[[[“cd”, “f”, “kl”]], [“a”], [“b”], [“c”], [“d”], [“e”], [“f”], [“g”], [“h”], [“i”], [“j”], [“k”], [“l”]]
输出: [null, false, false, false, true, false, true, false, false, false, false, false, true]

解释: StreamChecker streamChecker = new StreamChecker([“cd”, “f”,“kl”]);
streamChecker.query(“a”); // 返回 False
streamChecker.query(“b”); // 返回 False
streamChecker.query(“c”); // 返回 False
streamChecker.query(“d”); // 返回 True ,因为 ‘cd’ 在 words 中
streamChecker.query(“e”); // 返回 False
streamChecker.query(“f”); // 返回 True ,因为 ‘f’ 在 words 中
streamChecker.query(“g”); // 返回 False
streamChecker.query(“h”); // 返回 False
streamChecker.query(“i”); // 返回 False
streamChecker.query(“j”); // 返回 False
streamChecker.query(“k”); // 返回 False
streamChecker.query(“l”); // 返回 True ,因为 ‘kl’ 在 words 中

提示:

1 <= words.length <= 2000
1 <= words[i].length <= 200
words[i] 由小写英文字母组成
letter 是一个小写英文字母
最多调用查询 4 * 1e4 次

解析:

  • 每个查询提供一个字符,如果以当前字符为结尾的字符串在words中返回true,否则返回false;
  • 例如:words = [“cd”, “f”, “kl”],
  • query = k,不在words中,返回false;
  • query=l,发现 "kl"在words中返回true;
  • query = l, 所有查询组成的字符串变为了为"kll",l,kl,kll 均不在words中,因此返回false;
  • 首先,我们创建一个字典树,将words中单词全部反向插入,之所以反向插入,是因为查询的时候需要反向查找输入字符。
  • 可以看出我们需要将所有输入字符全部保存为字符串(记作stream),每次查询遍历字典树,遇到 isEnd=true的节点,说明该字符为结尾的后缀能匹配 words 中的某一字符串。

jiexi

代码:

class StreamChecker {
    struct Node{
        Node* son[26];
        bool isEnd;
    };

public:
    
    string stream="";
    Node* root;
    // 字典树插入,反向插入字符串s(模板写法)
    void insert(string& s){
        Node* cur=root;
        for(int i=s.size()-1;i>=0;i--){
            int c = s[i]-'a';
            // 节点不
            
            if(!cur->son[c]) 
                cur->son[c]=new Node();
            cur=cur->son[c];
        }
        cur->isEnd=true;
    }

    //  搜索,反向搜索stream
    bool search(){
        Node* cur=root;
        for(int i=stream.size()-1;i>=0;i--){
            int c = stream[i]-'a';
            // 如果不存在该后缀,返回false
            if(!cur->son[c]) 
                return false;
            cur=cur->son[c];
            // 遇到完整单词,说明后缀存在单词
            if(cur->isEnd)
                return true;
        }
        return false;
    }

    StreamChecker(vector<string>& words) {
        root=new Node();
        for(auto& a :words){
            insert(a);
        }
    }
    
    bool query(char letter) {
    	// 存储所有输入字符
        stream+=letter;
        return search();
    }
};

/**
 * Your StreamChecker object will be instantiated and called as such:
 * StreamChecker* obj = new StreamChecker(words);
 * bool param_1 = obj->query(letter);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值