按下述要求实现 StreamChecker 类:
StreamChecker(words):构造函数,用给定的字词初始化数据结构。 query(letter):如果存在某些 k >= 1,可以用查询的最后 k个字符(按从旧到新顺序,包括刚刚查询的字母)拼写出给定字词表中的某一字词时,返回 true。否则,返回 false。
示例:
StreamChecker streamChecker = new StreamChecker(["cd","f","kl"]); // 初始化字典 streamChecker.query('a'); // 返回 false streamChecker.query('b'); // 返回 false streamChecker.query('c'); // 返回 false streamChecker.query('d'); // 返回 true,因为 'cd' 在字词表中 streamChecker.query('e'); // 返回 false streamChecker.query('f'); // 返回 true,因为 'f' 在字词表中 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' 在字词表中。
提示:
1 <= words.length <= 2000 1 <= words[i].length <= 2000 字词只包含小写英文字母。 待查项只包含小写英文字母。 待查项最多 40000 个。
思路:由于待查项很大,我们并不能用传统的查询方式来做,因此我们可以考虑一波字典树,相信学过字典树的同学都对字典树的性质有所了解,字典树对于字符串的前缀查询有着非常好的性质。对于本题,由于题目要求我们只能匹配待查字符组成的串的后缀。我们可以考虑将查询表中的字符串倒着插入到字典树中,在查询时,我们可以将当前待查串从后往前在树上看是否存在一个后缀。
class StreamChecker { class node { boolean flag; node[] next; public node() { flag = false; next = new node[26]; } } node root; StringBuilder str; public StreamChecker(String[] words) { root = new node(); str = new StringBuilder(); for (int i = 0; i < words.length; i++) { node now = root; int len = words[i].length(); for (int j = len - 1; j >= 0; j--) { int k = words[i].charAt(j) - 'a'; if (now.next[k] == null) now.next[k] = new node(); now = now.next[k]; } now.flag = true; } } public boolean query(char letter) { str.append(letter); node now = root; for (int i = str.length() - 1; i >= 0; i--) { int k = str.charAt(i) - 'a'; if (now.next[k] != null) { now = now.next[k]; if (now.flag) return true; } else return false; } return false; } }